Ruby元类混淆

Per*_*llo 13 ruby metaclass

我知道ruby中的所有类都是元类Class的实例.而"常规"对象是这些类的实例(元类Class的实例).

但我一直在想,我的意思是类是对象的根,类本身就是Class的实例(称为元类,因为它的实例是类).我在一些博客中看到了newClass类的一些重写方法.

所以Class表现为一个类,但它的实例是类.所以看起来我们有一个圆圈,它看起来像类Class是它自己的一个实例.

我在这里显然错过了一点.班级的起源是什么?

这是一个令我困惑的例子:

class Class
  def new
    #something
  end
end
Run Code Online (Sandbox Code Playgroud)

但是关键字class意味着类Class的实例.那怎么做呢?

Jör*_*tag 30

这是怎么回事

容易:它没有.反正不是在Ruby中.

就像在大多数其他语言中一样,有一些核心实体被假设存在.它们从天而降,凭空出现,神奇地出现.

在Ruby中,一些神奇的东西是:

  • Object没有超类,但是你不能定义没有超类的类,隐式直接超类总是如此Object.[注意:可能有实现定义的超类Object,但最终会有一个没有超类的.)
  • Object是一个实例Class,它是(的一个子类)Object(这意味着它本身Object就是一个实例Object)
  • Class是它的子类Module,是它的一个实例Class
  • Class 是一个实例 Class

这些都不能用Ruby解释.

BasicObject,Object,Module并且Class都需要在同一时间,因为他们有循环依赖于弹入的存在.

仅仅因为这种关系不能用Ruby代码表示,并不意味着Ruby语言规范不能说它必须如此.由实现者决定如何做到这一点.毕竟,Ruby实现具有对程序员没有的对象的访问级别.

例如,Ruby实现可以首先创建BasicObject,设置其superclass指针和class指针null.

然后,它创建Object,将其superclass指针设置为BasicObject及其class指针null.

接下来,它创建Module,将其superclass指针设置为Object及其class指针null.

最后,它创建Class,设置其superclass指针Moduleclass指针null.

现在,我们可以覆盖BasicObject的,Object的,Module的,和Classclass指针指向Class,我们就大功告成了.

这很容易从系统外部进行,从内部看起来很奇怪.

但是,一旦它们确实存在,完全可以在纯Ruby中实现它们的大多数行为.您只需要这些类的非常准确的版本,感谢Ruby的开放类,您可以在以后添加任何缺少的功能.

在您的示例中,class Class不是创建一个名为的新类Class,而是重新打开运行时环境提供给我们的现有Class.

因此,完全可以解释Class#new纯Ruby中的默认行为:

class Class
  def new(*args, &block)
    obj = allocate # another magic thing that cannot be explained in Ruby
    obj.initialize(*args, &block)
    return obj
  end
end
Run Code Online (Sandbox Code Playgroud)

[注意:实际上,它initialize是私有的,因此您需要使用它obj.send(:initialize, *args, &block)来规避访问限制.]

BTW:Class#allocate是另一个神奇的东西.它在Ruby的对象空间中分配一个新的空对象,这是Ruby无法完成的.因此,Class#allocate必须由运行时系统提供.

  • 我认为你的意思是"`BasicObject`的超类是`nil`",因为`Object`的超类是`BasicObject`. (3认同)
  • @AndrewMarshall:这是1.9中的新功能.1.8只有`Object`没有`BasicObject`. (2认同)
  • @HolgerJust True,但1.8接近寿命终止,除非提问者指定我假设最新版本的Ruby. (2认同)