根据定义,对象的单例类也会继承该对象的超类的单例类。rubyBasicObject中没有任何超类,因为它是最基本的级别类
>> BasicObject.superclass
=> nil
Run Code Online (Sandbox Code Playgroud)
但是当相同的方法调用其单例类时,结果是:
>> BasicObject.singleton_class.superclass
=> Class
Run Code Online (Sandbox Code Playgroud)
为什么 ruby 中没有其他对象将该Class类作为其超类?
BasicObject 的超类 singleton_class 背后的逻辑是如何在 Ruby 中实现的?
一般来说,对象的单例类的超类就是该对象的类。即对于foo具有单例类的任何对象,以下内容成立:
foo.singleton_class.superclass == foo.class
Run Code Online (Sandbox Code Playgroud)
然而,对于类来说,这有点无聊:每个类的类都是Class,因此每个类的单例类的超类总是Class。
这并不是特别有用,因为它会打破一些合理的假设。例如,如果我有这样的东西:
class Super
def self.super_singleton_method; end
end
class Sub < Super; end
Run Code Online (Sandbox Code Playgroud)
我希望能够打电话Sub.super_singleton_method。然而,为了做到这一点,Super.singleton_class需要位于 的方法查找链中的某个位置Sub.singleton_class。
所以,对于类来说,规则有些不同:一个类的单例类的超类是该类的超类的单例类。即对于任何类Foo,以下内容成立:
Foo.singleton_class.superclass == Foo.superclass.singleton_class
Run Code Online (Sandbox Code Playgroud)
如果需要,您可以检查系统中的每个类是否都如此:
ObjectSpace.each_object(Class).select do |klass|
klass.singleton_class.superclass != klass.superclass.singleton_class
end
#=> [BasicObject]
Run Code Online (Sandbox Code Playgroud)
因此,正如您所看到的,该属性确实适用于除 之外的所有类BasicObject。
为什么BasicObject不同的简单答案是它BasicObject没有超类,因此我们不能应用该规则。因此,我们依赖于所有对象的更一般规则
foo.singleton_class.superclass == foo.class
Run Code Online (Sandbox Code Playgroud)
因此,AndBasicObject的类是Class
BasicObject.singleton_class.superclass == BasicObject.class
BasicObject.singleton_class.superclass == Class
Run Code Online (Sandbox Code Playgroud)
为什么 ruby 中没有其他对象将该
Class类作为其超类?
继承的唯一原因Class是重写继承或方法查找在 Ruby 中的工作方式。但 Ruby 不允许覆盖这一点。继承和方法查找的工作方式是语言规范的一部分,无法更改。因此,继承Class自是非法的:
class MyClass < Class; end
# can't make subclass of Class (TypeError)
Run Code Online (Sandbox Code Playgroud)
因此,除了类的单例类之外,不可能有任何对象具有Class其超类。(Ruby 当然可以打破自己的规则,因为它是制定规则的人。)
BasicObject 的超类 singleton_class 背后的逻辑是如何在 Ruby 中实现的?
事实并非如此。您无法解释它在 Ruby 中是如何工作的,因为它是 Ruby 本身定义的一部分。
它类似于 的Class子类Module,但它Module是一个类,即 的实例Class。您无法使用 Ruby 的规则从 Ruby 内部解释这一点,但是 Ruby 实现当然可以进行一些设置以使其正常工作,因为 Ruby 实现本身不必遵守 Ruby 的规则:它是唯一的执行规则,因此它可以选择不为自己执行规则。
\n\n根据定义,对象的单例类也会继承该对象的超类的单例类。
\n
我们不要认为这是理所当然的,而是要弄清楚为什么要这样实现。
\n在 Ruby 中,有实例方法和类方法。然而,类方法实际上是单例类的实例方法:
\nclass MyClass\n def foo\n end\n\n def self.bar\n end\nend\n\nMyClass.instance_methods(false)\n#=> [:foo]\n\nMyClass.singleton_class.instance_methods(false)\n#=> [:bar]\nRun Code Online (Sandbox Code Playgroud)\n如图所示:
\nMyClass ---> #<Class:MyClass>\nfoo bar\nRun Code Online (Sandbox Code Playgroud)\n现在,如果您创建一个子类MySubClass,它会从其超类继承实例方法和类方法MyClass:
class MySubClass < MyClass\nend\n\nMySubClass.instance_methods\n#=> [:foo, ...]\n\nMySubClass.singleton_class.instance_methods\n#=> [:bar, ...]\nRun Code Online (Sandbox Code Playgroud)\n为了实现这一点,必须为类和单例类建立继承:
\nclass MyClass\n def foo\n end\n\n def self.bar\n end\nend\n\nMyClass.instance_methods(false)\n#=> [:foo]\n\nMyClass.singleton_class.instance_methods(false)\n#=> [:bar]\nRun Code Online (Sandbox Code Playgroud)\nRuby 在内部对此进行了优化 \xe2\x80\x93 单例类仅在需要时创建。但从概念上讲,这就是发生的情况。
\n除此之外,MyClass它MySubClass已经附带了一些内置的类方法,最值得注意的.new是用于创建实例,但也.superclass.
您可能知道.new调用的默认实现.allocate的默认实现。因此,某个地方必须有一种包含这些方法的“根类”。由于它们是类方法,因此它必须位于单例类一侧的顶部:
MyClass ---> #<Class:MyClass>\nfoo bar\nRun Code Online (Sandbox Code Playgroud)\n这个神秘的顶级单例根类为所有其他类提供了基本的类方法......Class!
Class.instance_methods(false)\n#=> [:allocate, :superclass, :subclasses, :new]\nRun Code Online (Sandbox Code Playgroud)\n