这是如何工作的
简单:它没有。无论如何,不在 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 指针设置为Module,并将其class 指针设置为null。
现在,我们可以覆盖BasicObject's、Object's、Module's 和Class's class 指向Class 的指针,我们就完成了。
这在系统外部很容易做到,只是从内部看起来很奇怪。
然而,一旦它们确实存在,完全有可能在纯 Ruby 中实现它们的大部分行为。您只需要这些类的非常简单的版本,感谢 Ruby 的开放类,您可以在以后添加任何缺少的功能。
在您的示例中,class Class 并未创建名为 Class 的新类,而是重新打开运行时环境提供给我们的 现有 类 Class。
因此,完全可以用普通的 Ruby 来解释 Class#new 的默认行为:
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
[注意:实际上initialize是私有的,所以你需要使用obj.send(:initialize, *args, &block)来绕过访问限制。]
顺便说一句:Class#allocate 是另一个神奇的东西。它在 Ruby 的对象空间中分配一个新的空对象,这是 Ruby 无法做到的。因此,Class#allocate 也必须由运行时系统提供。