为什么“方法=”处理与其他任何方法一样?

时间:2013-09-26 16:41:05

标签: ruby

请考虑以下代码段:

class Example
  def my_attr=(value)
    @_my_attr = value
    @_my_attr * 3
  end
end

我希望表达式Example.new.my_attr = 5返回15,但结果证明是错误的。即使我明确调用=方法,也始终返回原始返回值:

Example.new.my_attr = 5 # => 5
Example.new.my_attr=(5) # => 5

Ruby如何以及为什么这样做? Ruby是否特别处理以=结尾的方法,还是其他机制?我想这排除了=方法的返回值的链接,对吧?有没有办法让Ruby表现得与众不同,或者这就是它的原因?

更新:感谢@jeffgran:

Example.new.send(:my_attr=, 5) # => 15

这是一种解决方法,但在另一个层面上更令人困惑,因为这意味着send显然并不总是等同于直接调用方法的行为。

1 个答案:

答案 0 :(得分:19)

这就是作业的工作原理;返回值被忽略,赋值表达式的结果始终是右侧值。这是Ruby语法的基本特征。 left-hand side = right-hand side始终评估为right-hand side,无论左手边是变量(x),方法(object.x),常量(X)还是任何表达。

来源:Programming Languages | Ruby IPA Ruby Standardization WG Draft,11.4.2.2.5,单方法分配


考虑分配链接x = y = 3

要使其正常工作,y = 3 的结果必须3,无论y=方法返回的实际值如何。 x = y = 3打算将y = 3; x = 3而不是视为y = 3; x = y,如果y=的返回值被视为y = 3的结果。

或者考虑可以使用所有其他地方的作业。有时候,而不是......

obj.x = getExpensiveThing()
if obj.x 
  ...

......我们写这个......

if obj.x = getExpensiveThing()

如果obj.x = ...的结果可能是任意的,无效,但我们知道它会起作用,因为{{1}的结果总是 obj.x = y

<强>更新

问题的comment表明:

  

有趣的是,我没有意识到这种情况。似乎method =返回给出的任何输入......

,这是一个重要的区别。这与方法赋值的返回值无关,它肯定“返回给定的任何输入”,它返回告诉它返回的任何内容。 / p>

重点是语言的语法忽略了返回值;赋值不会计算y方法的返回值,但返回值仍然存在,如问题本身所示:attr=。这是有效的,因为不是赋值。你是支持Ruby语言的那一部分。

再次更新

要明确:我的示例中的Example.new.send(:my_attr=, 5) # => 15x不应被解释为文字Ruby变量,它们是任务的任何有效左侧的占位符yx可以任何表达式yaobj.aCONSTANT_A,{{1 },它是所有相同的赋值的值始终是右侧。