Ruby元类混乱 [英] Ruby metaclass confusion
问题描述
我知道ruby中的所有类都是元类Class的实例.而常规"对象就是这些类的实例(元类Class的实例).
但是我一直在想,我的意思是类是对象的根,类本身是Class的实例(之所以称为Metaclass,是因为其实例是类).我在一些博客中看到Class类的方法new
的一些替代.
因此Class表现为类,但其实例是类.因此,似乎我们有一个圆圈,它看起来像是Class类是其自身的实例.
我在这里显然缺少一点.类Class的起源是什么?
这是一个使我感到困惑的例子:
class Class
def new
#something
end
end
但是关键字class
表示类Class的实例.那么,该如何工作?
这是怎么工作的
简单:并非如此.无论如何,不是在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
,Object
,Module
和Class
的class
指针,以指向Class
,我们就完成了. /p>
从系统外部很容易做到,从内部看起来很奇怪.
一旦要做存在,就完全有可能在纯Ruby中实现大多数行为.您只需要这些类的非常准系统的版本,这要归功于Ruby的开放类,您以后可以添加任何缺少的功能.
在您的示例中,class Class
并未创建名为Class
的新类,而是重新打开了运行时环境提供给我们的现有类Class
. /p>
因此,完全有可能用普通的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
也是运行时系统也必须提供的内容.
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).
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.
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.
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
But keyword class
implies an instance of class Class. So how do this work?
how do this work
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.
In Ruby, some of those magic things are:
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
None of these things can be explained in Ruby.
BasicObject
, Object
, Module
and Class
all need to spring into existence at the same time because they have circular dependencies.
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.
For example, the Ruby implementation could first create BasicObject
, setting both its superclass
pointer and its class
pointer to null
.
Then, it creates Object
, setting its superclass
pointer to BasicObject
and its class
pointer to null
.
Next, it creates Module
, setting its superclass
pointer to Object
and its class
pointer to null
.
Lastly, it creates Class
, setting its superclass
pointer to Module
and its class
pointer to null
.
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.
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.
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.
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
[Note: actually, initialize
is private, so you need to use obj.send(:initialize, *args, &block)
to circumvent the access restriction.]
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屋!