我想为对象定义一个新的getter方法。这是我在irb
写的代码:
> eigenclass = class << self; self; end
> eigenclass.class_eval { attr_reader :foo }
我想这段代码应该将foo
方法添加到自我对象中。但下一行说的不同
puts foo
=> nil
foo = 1
=> 1 #Why is there no exception?
puts foo
=> 1
puts @foo
=> nil
为什么?
答案 0 :(得分:3)
那是因为var = val
分配一个局部变量而不是调用setter
方法。
你需要在它前面添加self.
以便调用setter(以及实际的getter,以防你有一个同名的局部变量),这会抛出你期望的错误:
2.0.0p195 :001 > eigenclass = class << self; self; end
=> #<Class:#<Object:0x007fc6f98e24d0>>
2.0.0p195 :002 > eigenclass.class_eval { attr_reader :foo }
=> nil
2.0.0p195 :003 > foo
=> nil
2.0.0p195 :004 > foo = 20
=> 20
2.0.0p195 :005 > foo
=> 20
2.0.0p195 :006 > self.foo
=> nil
2.0.0p195 :007 > self.foo = 20
NoMethodError: undefined method `foo=' for main:Object
from (irb):7
答案 1 :(得分:3)
你犯了两个错误: a)如果你想要完整的访问者(getter和setter),你应该使用:
eigenclass.class_eval { attr_accessor :foo }
b)如果你想使用setter方法,你应该使用self
关键字,否则Ruby会设置一个局部变量:
self.foo = 1
# => 1
puts @foo
# => 1
或者,如果没有定义setter,您可以直接设置实例变量:
eigenclass.class_eval { attr_accessor :foo }
@foo = 1
puts @foo
# => 1