【问题标题】:In Ruby, if we define a method call "c=", why can't it be invoked by c = 3?在 Ruby 中,如果我们定义一个方法调用“c=”,为什么它不能被 c = 3 调用呢?
【发布时间】:2011-02-25 07:30:13
【问题描述】:

例如,如果我们

def c=(foo)
  p "hello"
end

c = 3
c=(3)

并且不会打印“你好”。我知道self.c = 3 可以调用它,但为什么呢?以及可以通过哪些其他方式调用它?

【问题讨论】:

标签: ruby


【解决方案1】:

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

  1. 至少 MRI 需要在解析时知道在给定范围内定义了哪些局部变量。但是,在解析时不知道是否定义了给定的方法。所以 ruby​​ 直到运行时才知道c = 3 是定义变量c 还是调用方法c=,这意味着它不知道在解析时是否定义了局部变量c。这意味着 MRI 需要更改它在解析器中处理局部变量的方式,以使其按您希望的方式工作。

  2. 如果方法为 c= 已定义,则无法定义名为 c 的局部变量。您可能会说没关系,因为具有相同名称的局部变量和方法无论如何都会令人困惑。但是考虑这种情况,您定义 method_missing 以便为每个可能的 foo 定义 foo=(例如 OpenStructs 的情况)。在这种情况下,根本无法定义局部变量。

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

【讨论】:

  • +1 用于提供完整的原因列表(而我只提供了行为/规则本身)。
【解决方案2】:

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

【讨论】:

  • 他贴的代码就够了。如果你做了self.c = 3,它会在 IRB 中工作。
  • 在旁注中,人们应该投票支持 sepp2k 的答案。它比我的更好,更完整。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-31
    • 2014-12-07
    • 2017-03-30
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    相关资源
    最近更新 更多