这是怎么工作的
容易:它没有。无论如何,不在 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'class指向 的指针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
[注:实际上initialize是私有的,所以你需要使用它obj.send(:initialize, *args, &block)来规避访问限制。]
顺便说一句:Class#allocate是另一种神奇的东西。它在 Ruby 的对象空间中分配一个新的空对象,这是 Ruby 无法做到的。因此,Class#allocate运行时系统也必须提供一些东西。