【问题标题】:Why do methods inside a class become instance methods instead of becoming singleton methods of the class itself?为什么类中的方法会变成实例方法而不是类本身的单例方法?
【发布时间】:2016-01-13 02:04:09
【问题描述】:

假设我有以下简单的类:

class C
  p self # => C

  def self.foo
    puts "foo"
  end

  def bar
    puts "bar"
  end
end

p C.foo # => "foo"
p C.bar # => "`<main>': undefined method `bar' for C:Class (NoMethodError)"

我知道self.foofoo 定义为C 的单例类中的实例方法。

为什么第二个方法没有像第一个一样在C 的单例类中定义?定义此方法时,self 仍然是 C

【问题讨论】:

    标签: ruby


    【解决方案1】:

    它的工作原理类似于消息发送和持续查找:

    • 消息发送的一般格式为foo.bar,将消息bar发送到foo。如果您遗漏foo,消息将被发送到默认接收者(即self)。
    • 常量查找的一般格式是Foo::Bar,在模块Foo中查找常量Bar。如果您忽略Foo,则将在默认常量上下文(或cref)中查找常量。
    • 方法定义的一般格式为def foo.bar,在foo的单例类中定义了方法bar。如果你省略了foo,该方法将在default definition context(或默认定义)中定义:

      • 在顶层,默认定义者是Object。 (另外,方法变为private。)
      • 在模块声明主体中,默认定义者是self(并且不是 self 的单例类,就像你假设的那样!)
      • 在方法体中,默认定义者是语法封闭模块。 (换句话说:def 不会更改默认定义。)
      • instance_eval 将默认定义者更改为接收者的单例类
      • class_eval 将默认定义者更改为接收者

    【讨论】:

    【解决方案2】:

    这是 ruby​​ 语言的约定。 (从概念上讲,您可以像考虑 Java 中的静态方法一样考虑这一点。它们不与类的任何实例相关联,而是与类本身相关联)

    bar 将成为从 C 实例化的对象的方法。 self.bar 将成为 C 本身的一种方法。

    Ruby 中的有趣之处在于 C 类本身就是一个对象(因此您可以用来构建对象的类定义就是一个对象本身)。这就是 self 的来源(即,在我自己身上定义它,而不是从将使用我作为蓝图构建的对象中定义它)阅读更多信息:Ruby craziness: Class vs Object?

    【讨论】:

    • 我知道C 是一个对象。我只是对默认定义方法的位置感到困惑。如果它们是在self 上定义的,那么bar 方法应该像第一个方法一样在C 类上定义。
    • 你对“自我”感到困惑......随着上下文的变化,自我也会发生变化。
    • 这正是 ruby​​ def 关键字的工作方式,它内置在 ruby​​ 中以这种方式工作。 def 将在 def method_name 中定义一个实例方法,但在 def someclass.method_name 中定义一个单例类方法。这就是def 的工作方式。因为大多数时候实例方法都是您想要的,它们是您定义的典型方法,所以这就是def 所做的。 ruby 是如何设计的,我知道你是如何一致地推理出来的,也许它不一致,这就是 ruby​​ 的设计方式。
    • 将 C 视为蓝图。你放在那里的所有东西(没有def)都会改变蓝图。当您通过 C.new 构建新对象时,您将获得蓝图定义的内容。当您在前面定义事物时,请考虑一下您正在定义一些与蓝图相关但未在蓝图本身中捕获的操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多