Ruby koans:对 koan 268 感到困惑
Ruby koans: Baffled by koan 268
我有 'solved' Ruby koan 268,但对我来说没有意义。该项目正在使用代理对象(我猜是一种适配器?)到 'impersonate' 电视 class。
这是我的代理 class 的结局:
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
稍后,Proxy Television 声明如下:
tv = Proxy.new(Television.new)
tv.power
tv.channel = 10
assert_equal [:power, :channel=], tv.messages
我的问题是,当我之前定义了 attr_accessor :messages 时,为什么我必须将 messages 方法添加到 Proxy?没有最后一个方法,公案就不会'pass'。 (tv.messages returns 无)。
我真的很想理解这一点,因为在我看来我是在通过 attr_accessor 和 messages 方法定义对@messages 的访问来重复自己。如果 attr_accessor 不能让我访问@messages,那有什么意义呢?
谢谢。
我 运行 这个代码在 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
是一个 class 方法,而不是实例方法。因此,您不能从 initialize
方法内部调用它。你必须把它放在外面,在 class 体内。然后它将正确设置访问器,它首先会按您预期的那样工作:
class A
attr_accessor :m
def a(i)
@m = i
end
end
a = A.new
a.a 'hey'
a.m # => "hey"
这个 method_missing
的定义掩盖了错误:任何对不存在的方法的调用只是 returns nil 而不是引发 NameError。
特别是你对 attr_accessor
的调用没有做任何事情,因为 attr_accessor
不是实例方法,所以 method_missing
被调用并吞下了你的错误,所以你对 [需要 =14=] 才能获得 @messages
的值。如果在 initialize
方法之外调用 attr_accessor
,那么 messages
的定义确实是多余的。
如果您省略 messages
方法,那么 proxy.messages
最终只会调用 method_missing
并且(除非电视有这样的方法)returns nil。
我有 'solved' Ruby koan 268,但对我来说没有意义。该项目正在使用代理对象(我猜是一种适配器?)到 'impersonate' 电视 class。
这是我的代理 class 的结局:
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
稍后,Proxy Television 声明如下:
tv = Proxy.new(Television.new)
tv.power
tv.channel = 10
assert_equal [:power, :channel=], tv.messages
我的问题是,当我之前定义了 attr_accessor :messages 时,为什么我必须将 messages 方法添加到 Proxy?没有最后一个方法,公案就不会'pass'。 (tv.messages returns 无)。
我真的很想理解这一点,因为在我看来我是在通过 attr_accessor 和 messages 方法定义对@messages 的访问来重复自己。如果 attr_accessor 不能让我访问@messages,那有什么意义呢?
谢谢。
我 运行 这个代码在 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
是一个 class 方法,而不是实例方法。因此,您不能从 initialize
方法内部调用它。你必须把它放在外面,在 class 体内。然后它将正确设置访问器,它首先会按您预期的那样工作:
class A
attr_accessor :m
def a(i)
@m = i
end
end
a = A.new
a.a 'hey'
a.m # => "hey"
这个 method_missing
的定义掩盖了错误:任何对不存在的方法的调用只是 returns nil 而不是引发 NameError。
特别是你对 attr_accessor
的调用没有做任何事情,因为 attr_accessor
不是实例方法,所以 method_missing
被调用并吞下了你的错误,所以你对 [需要 =14=] 才能获得 @messages
的值。如果在 initialize
方法之外调用 attr_accessor
,那么 messages
的定义确实是多余的。
如果您省略 messages
方法,那么 proxy.messages
最终只会调用 method_missing
并且(除非电视有这样的方法)returns nil。