这听起来很奇怪不是吗?
class Dummy
def foo=(value); end
end
Dummy.new.foo = 1 { |x| x } # => syntax error
Dummy.new.foo=(1) { |x| x } # => syntax error
我尝试了每一个空白,括号,逗号的排列;没运气。我很困惑。我从不怀疑用'='结尾的方法很特别。这是一个错误吗?是打算吗?如果打算,为什么?有记录吗?哪里?请分享见解。
感谢
PS。 ruby是1.9.2p290(2011-07-09修订版32553)[x86_64-darwin11.0.1]
答案 0 :(得分:2)
以=
结尾的方法的语法糖确实使它变得特别。你仍然可以做一些事情,比如将多个参数传递给该方法,或传递一个块,但不能以任何漂亮或方便的方式:
class Foo
def bar=(a,b=nil)
p [a,b]
if block_given?
yield "hi"
else
puts "No block"
end
end
end
f = Foo.new
f.bar = 42
#=> [42, nil]
#=> No block
f.bar = 42, 17
#=> [[42,17], nil]
#=> No block
f.send(:bar=,42,17) do |x|
puts "x is #{x.inspect}"
end
#=> [42, 17]
#=> x is "hi"
这些方法特殊的另一种方式是,当使用语法糖调用时,它们会计算为右手值,而不是方法的返回值:
class Foo
def bar=(a)
return 17 # really explicit
end
end
f = Foo.new
x = (f.bar = 42)
p x
#=> 42
x = f.send(:bar=,42)
p x
#=> 17
答案 1 :(得分:0)
方法本身并不特别,但更多的是与Ruby如何处理分配(如foo = bar
)有关。首先评估右侧,然后评估左侧并采取适当的措施。如果左侧是对象属性,则调用适当的setter方法。
所以在你的例子中:
Dummy.new.foo = 1 { |x| x }
第一个ruby尝试评估1 { |x| x }
,这是导致语法错误的原因。
Dummy.new.foo=something
实际上并不意味着“调用名为foo=
的方法”,但实际上意味着更像“评估something
”,然后确定`Dummy.new.foo
是什么,如果它看起来像一个对象属性,请在名称中添加=
并调用该方法“。这就是为什么Dummy.new.foo=
和Dummy.new.foo =
都以相同的方式工作的原因。
您可以使用send
调用这些方法,并可以使用以下方法传递一个块:
Dummy.new.send "foo=", 2 do
puts "HI"
end
这是因为使用send
您可以明确命名要调用的方法。
当然,最终的结果是以=
结尾的方法似乎有一些你需要注意的“特殊”行为,但了解实际情况可能会有用。