請原諒總newbiew問題,但爲什麼@game_score總是零?總新手:在Ruby中的實例變量?
#bowling.rb
class Bowling
@game_score = 0
def hit(pins)
@game_score = @game_score + pins
end
def score
@game_score
end
end
請原諒總newbiew問題,但爲什麼@game_score總是零?總新手:在Ruby中的實例變量?
#bowling.rb
class Bowling
@game_score = 0
def hit(pins)
@game_score = @game_score + pins
end
def score
@game_score
end
end
讓我們通過代碼,我們應?
#bowling.rb
class Bowling
@game_score = 0 # (1)
此時(1),我們還在類Bowling
內。請記住:類只是其他任何對象。因此,此時您將0
分配給類對象Bowling
的實例變量@game_score
。
def hit(pins)
@game_score = @game_score + pins # (2)
現在(2),我們是Bowling
類的實例方法內部。 I.e .:這是一種將屬於Bowling
的實例的方法。所以,現在實例變量@game_score
屬於Bowling
類的實例,而不屬於類本身。
由於這個實例變量初始化從來沒有任何東西,它會評估爲nil
(在Ruby中,未初始化的變量永遠評估爲nil
),所以這個計算結果爲@game_score = nil + pins
,自nil
沒有一個#+
方法,這將導致NoMethodError
異常被引發。
end
def score
@game_score # (3)
在這裏,(3),我們又是Bowling
類的實例方法內。這將始終評估爲nil
,因爲我上面列出的理由:@game_score
從未初始化,因此它的計算結果爲nil
。
end
end
我們可以使用Ruby的反射能力,看看這是怎麼回事:
p Bowling.instance_variable_get(:@game_score) # => 0
b = Bowling.new
p b.instance_variable_get(:@game_score) # => nil
現在讓我們注入一個值到實例變量:
b.instance_variable_set(:@game_score, 1)
p b.score # => 1
b.hit(3)
p b.score # => 4
所以,我們看到一切正常,我們只需要弄清楚如何確保實例變量被初始化。
要做到這一點,我們需要編寫一個初始化方法。奇怪的是,初始化方法實際上是一個私人的實例方法,稱爲initialize
。 (之所以initialize
是實例方法,而不是一個類的方法,其實很簡單的Ruby拆分對象創建在兩個階段:。內存分配和對象的初始化內存分配由類方法來完成所謂的alloc
和對象初始化是由實例執行方法調用initialize
(Objective-C程序員會認識到這一點)alloc
是一個類方法的原因很簡單,就是在這個執行過程中沒有實例,而且initialize
是一個實例方法是對象初始化顯然是每個對象。爲方便起見,有一個叫new
標準廠房類方法調用都alloc
和initialize
你。)
class Bowling
def initialize
@game_score = 0
end
end
讓我們來測試這一點:
c = Bowling.new
p c.score # => 0
c.hit(2)
p c.score # => 2
BTW:只是一些輕微的紅寶石風格提示:縮進2個空格,而不是1個標籤。而你的hit
方法更慣用@game_score += pins
。
因爲你沒有
def initialize
@game_score = 0
end
類定義的分配沒有做什麼你認爲它是幹什麼的,當hit
被調用它不能添加到nil
做。
如果您現在詢問發生了什麼事@game_score
?,好吧,永遠記得類是一個對象和對象是一個類。
Ruby類有這種類似禪宗的「真實」存在的方式很酷。 Ruby並不完全具有命名類,相反,類名是對類Class
的對象的引用。通過在實例方法的外部分配@game_score
,您創建了一個類實例變量,該類對象的一個屬性爲Bowling
,它是類Class
的一個實例。這些對象通常不是很有用。 (參見第1章,Ruby之道,哈爾富爾頓。)
@game_score
定義有被稱爲類實例變量,這對於單例類對象中定義的變量:
class << Bowling
attr_accessor :game_score
end
Bowling.game_score #=> 0
這是因爲您可以區別於爲實例對象定義的正常的實例變量。
@game_score將永遠不會得到一個零值在這裏 - 你需要把它裏面初始化,如
高清初始化 @game_score = 0 結束
這是Java的方式,歡迎紅寶石:d – khelll 2009-10-10 18:56:00