2

以下内容来自The Rspec Book。我想知道为什么messages << messageindef puts不是@messages << message。我知道那||= []是记忆,我也知道那@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
4

3 回答 3

5

因为

def puts(message)
  messages << message
end

然后打电话

def messages
  @messages ||= []
end

如果它不存在,则||= []分配一个空数组。@messages这就是为什么puts(message)@messages直接使用。

编辑:如果你@messages << message直接这样做,@messages那可能还不存在。这就是为什么你要通过messages

于 2013-10-20T11:18:00.620 回答
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"]
于 2013-10-20T11:24:11.127 回答
5

作者选择了惰性对象创建,消息不是在构造函数中创建,而是在 getter 方法中创建。只要你不直接访问@messages,你就不会得到一个 nil 异常。

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
于 2013-10-20T11:30:57.157 回答