Ruby koans:被koan 268困惑

时间:2015-01-06 15:22:11

标签: ruby proxy

我已经解决了' Ruby koan 268,但它对我没有意义。该项目正在使用代理对象(我想作为一种适配器?)来模仿'电视课 以下是我的Proxy类的结果:

class Proxy
  def initialize(target_object)
    @object = target_object
    # ADD MORE CODE HERE
    attr_accessor :messages
    @messages = []
  end

  # WRITE CODE HERE
  def method_missing(method_name, *args)
    if @object.respond_to?(method_name)
      @messages.push(method_name)
      @object.send(method_name, *args)
    end
  end

  def messages 
    @messages
  end
end

后来,代理电视宣布如下:

tv = Proxy.new(Television.new)    
tv.power
tv.channel = 10
assert_equal [:power, :channel=], tv.messages

我的问题是,当我更早地定义了attr_accessor:消息时,为什么我必须将消息方法添加到Proxy?没有最后一种方法,公案就没有通过。 (tv.messages返回nil)。

我真的很想理解这一点,因为在我看来,我通过attr_accessor和messages方法定义访问@消息来重复自己。如果attr_accessor没有让我访问@messages,那么它的重点是什么?

感谢。

2 个答案:

答案 0 :(得分:0)

我在ruby 2.1.5p273上运行了这段代码:

class A
  def initialize
    attr_accessor :m
  end

  def a(i)
    @m = i
  end
end

a = A.new

这会引发错误:

NoMethodError: undefined method `attr_accessor' for #<A:0x007f8313022220>
  from (irb):3:in `initialize'

问题是attr_accessor是一个类方法,而不是实例方法。因此,您无法从initialize方法中调用它。你必须把它放在课外体内。然后它将正确设置访问器,它将首先按照您的预期工作:

class A
  attr_accessor :m

  def a(i)
    @m = i
  end
end

a = A.new
a.a 'hey'
a.m # => "hey"

答案 1 :(得分:0)

method_missing的这个定义掩盖了错误:对非existant方法的任何调用只返回nil而不是引发NameError。

特别是您对attr_accessor的调用没有做任何事情,因为attr_accessor不是实例方法,因此调用method_missing并吞下您的错误,因此您对{的定义需要{1}}才能获得messages的值。如果您在@messages方法之外致电attr_accessor,那么initialize的定义确实是多余的。

如果您省略了messages方法,那么messages只会调用proxy.messages并且(除非电视有这样的方法)返回nil。