2013-10-20 67 views
2

以下是來自The Rspec Book。我想知道爲什麼messages << messagedef puts不是@messages << message。我明白是memoization,並且我也明白@messages是一個實例變量。那麼,它應該用於同一個班級嗎?還是它是一個錯字?爲什麼不使用「@ messages」?

class Output 
    def messages 
    @messages ||= [] 
    end 

    def puts(message) 
    messages << message 
    end 
end 

def output 
    @output ||= Output.new 
end 

Given /^I am not yet playing$/ do 
end 

When /^I start a new game$/ do 
    game = Codebreaker::Game.new(output) 
    game.start 
end 

Then /^I should see "([^"]*)"$/ do |message| 
    output.messages.should include(message) 
end 
+2

感謝-1個人,非常鼓舞人心。請解釋我爲什麼得到-1? – shin

+1

問題對我來說似乎沒問題+1 :) – tihom

回答

5

我想你的混亂是@messages變量和messages方法

class Output 
    def messages 
    @messages ||= [] 
    end 

    def puts(message) 
    messages << message #=> here `messages` refer to the method above 
    end 
end 

之間。這裏是一個簡單的例子

class Output 
    def m 
    @messages ||= [] 
    end 

    def puts(message) 
    m << message #=> method `m` 
    end 
end 

v = Output.new 
v.puts "blah" 
v.m #=> ["blah"] 

實施例2(用於更清楚)

class Output 
    def m 
    @messages ||= [] 
    end 

    def puts(message) 
    m << message #=> here `m` refer to the method above 
    end 

    def show_at_messages_variable 
    @messages 
    end 
end 

v = Output.new 
v.puts "blah" 
v.show_at_messages_variable #=> ["blah"] 
5

由於

def puts(message) 
    messages << message 
end 

然後調用

def messages 
    @messages ||= [] 
end 

,如果它不存在的分配一個空數組@messages。這就是爲什麼puts(message)不直接使用@messages

編輯: 如果您直接做@messages << message,那麼@messages可能還不存在。這就是爲什麼你通過messages來代替。

+0

你能解釋一下爲什麼puts(消息)不使用部分嗎? – shin

5

的作者選擇了懶惰的對象創建, 消息不是在構造函數中創建的,而是在getter方法中創建的。 只要你不直接訪問@messages,你不能得到一個零例外。

class Output 
    def messages 
    @messages ||= [] 
    end 

    def puts(message) 
    # If i was to use the variable @messages at this point, 
    # i would get a nil exception, the array was never allocated. 
    # Using the getter ensures that the array is allocated. 
    messages << message 
    end 
end 

如果你有一個獨特的不需要懶惰地創建你的對象,你可以按照以下方式編寫相同的類。

class Output 
    attr_reader :messages 

    def initialize(message) 
    @messages = [] 
    end 

    def puts(message) 
    # messages was created when this object was initialized, 
    # thus it is perfectly safe to use here. 
    @messages << message 
    end 
end 
相關問題