2013-10-20 39 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 
相关问题