2016-04-30 11 views
8

एक सरणी को अद्यतन करने की अनुमति न दें मैं एक साधारण टिक टैक पैर गेम लिख रहा हूं, जिसमें मेरे पास बोर्ड, प्लेयर, कंप्यूटर और गेम के लिए एक कक्षा है। मेरे बोर्ड वर्ग में, मैंने एक वर्ग वैरिएबल @बोर्ड (जो एक सरणी है) को attr_reader के रूप में सेट किया है, जिसे सीधे इसे लिखने की अनुमति नहीं देनी चाहिए। हालांकि निम्नलिखित (के रूप में इरादा) काम नहीं करेगारूबी: एक वर्ग परिवर्तनीय

game_board = Board.new 
game_board.board = "some junk" 

निम्नलिखित काम है, जो मैं

game_board = Board.new 
game_board.board[0] = "some junk" 

मैं कैसे लिखा जा रहा से वर्ग सरणी चर @board रोकूँ हो नहीं करना चाहते करता है सेवा मेरे? नीचे वर्तमान वर्ग कोड:

class Board 
    attr_reader :board 

    def initialize 
    create_board 
    end 

    private 
    def create_board 
    @board = Array.new(3).map{Array.new(3)} 
    end 
end 

game_board = Board.new 
game_board.board 
#=> [[nil,nil,nil],[nil,nil,nil],[nil,nil,nil]] 
game_board.board = "junk" 
#=> undefined method 'board =' 

game_board.board[0] = "junk" 
game_board.board 
#=> ["junk",[nil,nil,nil],[nil,nil,nil]] #I don't want to allow this! 

मैं इस googling की कोशिश की, लेकिन कोई लाभ नहीं हुआ, हालांकि मैं पूरी तरह से शुरुआत कर रहा हूँ, इसलिए मैं सही खोज शब्दों

+1

"अपरिवर्तनीय सरणी" और "फ्रीज सरणी" के लिए खोजें। अपरिवर्तनीयता को विशिष्ट वस्तु द्वारा लगाया जाना चाहिए क्योंकि 'x.y = a' के पास' x.y.z = b' में * असाइनमेंट * के बारे में कोई संबंध या विचार नहीं है (सिवाय इसके कि 'x.y' पहले किसी ऑब्जेक्ट को हल किया गया है)। – user2864740

+1

शब्दावली नोट: '@ बोर्ड' कक्षा चर नहीं है, यह एक आवृत्ति चर है। कक्षा चर दो '@' से शुरू होता है, उदा। '@@ board'। –

उत्तर

7

मेरा मानना ​​है कि आप बनाने की जरूरत का उपयोग नहीं किया जा सकता है सरणी अपरिवर्तनीय।

आप इसे प्राप्त करने के लिए Array#freeze का उपयोग कर सकते हैं।

उसके बाद आपका कैसा दिखना चाहिए: अपने दूसरे उदाहरण चल पर

>> game_board = Board.new 
#<Board:0x00000001648b50 @board=[[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]> 
>> game_board.board = "some junk" 
NoMethodError: undefined method `board=' for #<Board:0x00000001648b50> 
    from (irb):14 
    from /home/alfie/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>' 

:

class Board 
    attr_reader :board 

    def initialize 
    create_board 
    end 

    private 
    def create_board 
    @board = Array.new(3).map{Array.new(3).freeze}.freeze 
    end 
end 

अपना पहला उदाहरण चल पर

>> game_board = Board.new 
#<Board:0x00000001639e48 @board=[[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]> 
>> game_board.board[0] = "some junk" 
RuntimeError: can't modify frozen Array 
    from (irb):16 
    from /home/alfie/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>' 
6

केवल attr_reader को परिभाषित करना, बिना attr_writer, असाइनमेंट को रोक देगा @board परिवर्तनीय पर केवल ents। दूसरे शब्दों में, कक्षा @board में संग्रहीत किए गए संशोधित करने के लिए एक इंटरफ़ेस का खुलासा नहीं करती है, लेकिन प्रारंभिक मान में संशोधन को रोकने के लिए कुछ भी नहीं करता है।

आप freeze इस्तेमाल कर सकते हैं:

def create_board 
    @board = Array.new(3) { Array.new(3).freeze } 
    @board.freeze 
end 

उच्च-स्तरीय सरणी बर्फ़ीली

(भी, तुम वहाँ map जरूरत नहीं है) और एकत्रित लोगों को आप क्या वर्णन करना होगा, लेकिन मुझे लगता है कि यह आपके गेम को भी तोड़ देगा क्योंकि संशोधन पूरी तरह असंभव होगा।

मेरा सुझाव है कि @board का खुलासा न करें और इसे निजी मानें। इसके बाद आपको बोर्ड में मूल्य निर्धारित करने के लिए एक इंटरफेस का पर्दाफाश करना चाहिए, और बोर्ड के एक पाठक प्रतिनिधित्व को वापस करने के लिए एक विधि प्रदान करना चाहिए।

class Board 

    def initialize 
    create_board 
    end 

    def []=(x, y, value) 
    @board[x][y] = value 
    end 

    def board 
    @board.map { |a| a.dup.freeze }.freeze 
    end 

    private 

    def create_board 
    @board = Array.new(3) { Array.new(3) } 
    end 
end 


b = Board.new 
b.board 
# => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]] 

b[1,2] = "x" 
b[0,0] = "o" 
b.board 
# => [["o", nil, nil], [nil, nil, "x"], [nil, nil, nil]] 

b.board[0] = "junk" 
# RuntimeError: can't modify frozen Array 
b.board[0][1] = "junk" 
# RuntimeError: can't modify frozen Array 
b.board 
# => [["o", nil, nil], [nil, nil, "x"], [nil, nil, nil]] 
संबंधित मुद्दे