这是怎么工作的
容易:它没有。无论如何,不在 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
运行时系统也必须提供一些东西。