【发布时间】:2011-02-25 07:30:13
【问题描述】:
例如,如果我们
def c=(foo)
p "hello"
end
c = 3
c=(3)
并且不会打印“你好”。我知道self.c = 3 可以调用它,但为什么呢?以及可以通过哪些其他方式调用它?
【问题讨论】:
标签: ruby
例如,如果我们
def c=(foo)
p "hello"
end
c = 3
c=(3)
并且不会打印“你好”。我知道self.c = 3 可以调用它,但为什么呢?以及可以通过哪些其他方式调用它?
【问题讨论】:
标签: ruby
c = 3(和c = (3),完全等价于它)总是被解释为局部变量赋值。您可能会说,只有在 self 上没有定义方法 c= 时,它才应该被解释为局部变量赋值,但是这样做存在各种问题:
至少 MRI 需要在解析时知道在给定范围内定义了哪些局部变量。但是,在解析时不知道是否定义了给定的方法。所以 ruby 直到运行时才知道c = 3 是定义变量c 还是调用方法c=,这意味着它不知道在解析时是否定义了局部变量c。这意味着 MRI 需要更改它在解析器中处理局部变量的方式,以使其按您希望的方式工作。
如果方法为 c= 已定义,则无法定义名为 c 的局部变量。您可能会说没关系,因为具有相同名称的局部变量和方法无论如何都会令人困惑。但是考虑这种情况,您定义 method_missing 以便为每个可能的 foo 定义 foo=(例如 OpenStructs 的情况)。在这种情况下,根本无法定义局部变量。
您无法确定一个对象是否响应c= 而无需运行它,因为它可能由method_missing 处理。所以整个事情实际上是无法确定的。
【讨论】:
因为局部变量优先于以前定义的同名方法/变量。在这种情况下,您需要使用 'self' 进行限定,以便 c 不会被解释为局部变量的声明/赋值。
【讨论】:
self.c = 3,它会在 IRB 中工作。
只有当代码不能被解释为变量赋值时,Ruby 才会调用这种方法。没有更好的方法来强制方法调用。
self.c = 1
send(:c=, 1)
__send__(:c=, 1)
method(:c=).call(1)
method(:c=)[1]
【讨论】: