在Ruby中,如果我们定义一个方法调用“c =”,为什么它不能被c = 3调用?

例如,如果我们

def c=(foo) p "hello" end c = 3 c=(3) 

并且不打印“你好”。 我知道它可以被self.c = 3调用,但为什么呢? 以及在其他方面可以调用它?

c = 3 (和c = (3) ,它完全等价)总是被解释为局部变量赋值。 您可能会说只有在方法c=未在self上定义时才应将其解释为局部变量赋值,但是存在各种问题:

  1. 至少MRI需要在​​分析时知道在给定范围内定义了哪些局部变量。 但是,在解析时不知道是否定义了给定方法。 所以ruby无法知道c = 3是否定义变量c或者调用方法c=直到运行时,这意味着它不知道是否在解析时定义了局部变量c 。 这意味着MRI需要改变它在解析器中处理局部变量的方式,以使其像你想要的那样工作。

  2. 如果已定义方法c=则无法定义名为c的局部变量。 您可能会说这没关系,因为无论如何都要使用同名的局部变量和方法。 但是请考虑这种情况,您可以在其中定义method_missing以便为每个可能的foo定义foo= (例如,在OpenStruct上就是这种情况)。 在这种情况下,根本无法定义局部变量。

  3. 您无法确定对象是否响应c=而不运行它,因为它可能由method_missing处理。 所以整件事实际上是不可判定的。

因为局部变量优先于先前定义的具有相同名称的方法/变量。 在这种情况下,您需要使用’self’进行限定,以便c不被解释为局部变量的声明/赋值。

如果代码不能被解释为变量赋值,Ruby只会调用这种方法。 没有更好的方法来强制方法调用。

 self.c = 1 send(:c=, 1) __send__(:c=, 1) method(:c=).call(1) method(:c=)[1]