正如 Martin 所说,这会破坏分配链。
ruby 分配方法被定义为工作的方式扩展MyClass.property = 3
为(lambda { |v| MyClass.send('property=', v); v })[3]
(不是真的,但这显示了链接是如何工作的)。赋值的返回值始终是赋值的值。
如果您想查看MyClass#property=
方法的结果,请使用#send
:
irb> o = Object.new
=> #<Object:0x15270>
irb> def o.x=(y)
irb> @x = y+1
irb> puts "y = #{y}, @x = #@x"
irb> true
irb> end
=> nil
irb> def o.x
irb> puts "@x = #@x"
irb> @x
irb> end
=> nil
irb> o.x = 4
y = 4, @x = 5
=> 4
irb> o.x
@x = 5
=> 5
irb> o.send('x=', 3)
y = 3, @x = 4
=> true
然而,红宝石的做法是有例外——如果在分配过程中出现问题,引发异常。然后,如果出现问题,所有调用者都必须处理它,这与返回值不同,返回值很容易被忽略:
# continued from above...
irb> def o.x=(y)
irb> unless y.respond_to? :> and (y > 0 rescue false)
irb> raise ArgumentError, 'new value must be > 0', caller
irb> end
irb> @x = y + 1
irb> puts "y = #{y}, @x = #@x"
irb> end
=> nil
irb> o.x = 4
y = 4, @x = 5
=> 4
irb> o.x = 0
ArgumentError: new value must be > 0
from (irb):12
from :0
irb> o.x = "3"
ArgumentError: new value must be > 0
from (irb):13
from :0
irb> o.x
@x = 5
=> 5