Ruby 元类混淆 [英] Ruby metaclass confusion
问题描述
我知道 ruby 中的所有类都是元类 Class 的实例.而那个常规"对象是这些类的实例(元类 Class 的实例).
I understand that all classes in ruby are instances of metaclass Class. And that "regular" objects are instances of these classes (the instances of metaclass Class).
但我一直在想,我的意思是类是对象的根,类本身就是类的实例(称为元类,因为它的实例是类).我在一些博客中看到了 Class 类的方法 new
的一些覆盖.
But I keep wondering, I mean classes are root of objects, classes are themselves instances of Class (called metaclass because its instances are classes). I saw in some blogs some overriding of method new
, of class Class.
所以 Class 表现为一个类,但它的实例是类.所以看起来我们有一个圆圈,看起来类Class是它自己的一个实例.
So Class behaves as a class, but its instances are classes. So it seems we have a circle, it looks likes class Class is an instance of itself.
我显然在这里遗漏了一点.Class类的由来是什么?
I'm clearly missing a point here. What is the origin of class Class?
这是一个让我困惑的例子:
Here's an example that's confusing me:
class Class
def new
#something
end
end
但是关键字class
暗示类Class 的一个实例.那么这是如何工作的?
But keyword class
implies an instance of class Class. So how do this work?
推荐答案
这是如何工作的
简单:没有.无论如何,不是在 Ruby 中.
Easy: it doesn't. Not in Ruby, anyway.
就像在大多数其他语言中一样,有一些核心实体只是假设存在.他们从天而降,凭空出现,神奇地出现.
Just like in most other languages, there are some core entities that are simply assumed to exist. They fall from the sky, materialize out of thin air, magically appear.
在 Ruby 中,其中一些神奇的东西是:
In Ruby, some of those magic things are:
Object
没有超类,但是你不能定义一个没有超类的类,隐式的直接超类总是Object
.[注意:Object
可能有实现定义的超类,但最终会有一个没有超类.]Object
是Class
的一个实例,它是Object
的子类(即间接Object
是Object
本身的一个实例)Class
是Module
的子类,是Class
的一个实例Class
是Class
的一个实例
Object
doesn't have a superclass, but you cannot define a class with no superclass, the implicit direct superclass is alwaysObject
. [Note: there may be implementation-defined superclasses ofObject
, but eventually, there will be one which doesn't have a superclass.]Object
is an instance ofClass
, which is a subclass ofObject
(which means that indirectlyObject
is an instance ofObject
itself)Class
is a subclass ofModule
, which is an instance ofClass
Class
is an instance ofClass
这些东西都不能用 Ruby 来解释.
None of these things can be explained in Ruby.
BasicObject
、Object
、Module
和 Class
都需要同时出现,因为它们有循环依赖.
BasicObject
, Object
, Module
and Class
all need to spring into existence at the same time because they have circular dependencies.
仅仅因为这种关系不能用 Ruby 代码表达,并不意味着 Ruby 语言规范不能说它必须如此.这取决于实现者想出一种方法来做到这一点.毕竟,Ruby 实现可以访问您作为程序员所没有的对象.
Just because this relationship cannot be expressed in Ruby code, doesn't mean the Ruby Language Specification can't say it has to be so. It's up to the implementor to figure out a way to do this. After all, the Ruby implementation has a level of access to the objects that you as a programmer don't have.
例如,Ruby 实现可以首先创建 BasicObject
,将它的 superclass
指针和它的 class
指针设置为 null代码>.
For example, the Ruby implementation could first create BasicObject
, setting both its superclass
pointer and its class
pointer to null
.
然后,它创建Object
,将它的superclass
指针设置为BasicObject
,将它的class
指针设置为null
.
Then, it creates Object
, setting its superclass
pointer to BasicObject
and its class
pointer to null
.
接下来,它创建Module
,将它的superclass
指针设置为Object
,将它的class
指针设置为null
.
Next, it creates Module
, setting its superclass
pointer to Object
and its class
pointer to null
.
最后,它创建了Class
,将它的superclass
指针设置为Module
并将它的class
指针设置为null
.
Lastly, it creates Class
, setting its superclass
pointer to Module
and its class
pointer to null
.
现在,我们可以覆盖BasicObject
、Object
、Module
和Class
的 class
指针指向 Class
,我们就完成了.
Now, we can overwrite BasicObject
's, Object
's, Module
's, and Class
's class
pointer to point to Class
, and we're done.
这在系统外部很容易做到,只是从内部看起来很奇怪.
This is easy to do from outside the system, it just looks weird from the inside.
一旦它们确实存在,就完全有可能在普通 Ruby 中实现它们的大部分行为.您只需要这些类的非常简单的版本,感谢 Ruby 的开放类,您可以在以后添加任何缺失的功能.
Once they do exist, however, it is perfectly possible to implement most of their behavior in plain Ruby. You only need very barebones versions of those classes, thanks to Ruby's open classes, you can add any missing functionality at a later time.
在您的示例中,class Class
不是创建名为 Class
的新类,而是重新打开 现有 类 Class
,这是运行时环境给我们的.
In your example, the class Class
is not creating a new class named Class
, it is reopening the existing class Class
, which was given to us by the runtime environment.
所以,完全可以用普通的 Ruby 来解释 Class#new
的默认行为:
So, it is perfectly possible to explain the default behavior of Class#new
in plain 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)
来规避访问限制.]
[Note: actually, initialize
is private, so you need to use obj.send(:initialize, *args, &block)
to circumvent the access restriction.]
顺便说一句:Class#allocate
是另一种神奇的东西.它在 Ruby 的对象空间中分配了一个新的空对象,这是 Ruby 无法做到的.因此,Class#allocate
也必须由运行时系统提供.
BTW: Class#allocate
is another one of those magic things. It allocates a new empty object in Ruby's object space, which is something that cannot be done in Ruby. So, Class#allocate
is something that has to be provided by the runtime system as well.
这篇关于Ruby 元类混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!