为什么类中的方法成为实例方法而不是成为类本身的单例方法?

时间:2015-10-14 20:01:56

标签: ruby

假设我有以下简单类:

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。

2 个答案:

答案 0 :(得分:1)

它是红宝石语言的惯例。 (从概念上讲,你可以想到这就像你在Java中考虑静态方法一样。它们不与类的任何实例相关联,而是与类本身相关联)

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

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

答案 1 :(得分:1)

它与消息发送和常量查找类似:

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

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