Ruby元类混乱 [英] Ruby metaclass confusion

查看:83
本文介绍了Ruby元类混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道ruby中的所有类都是元类Class的实例.而常规"对象就是这些类的实例(元类Class的实例).

但是我一直在想,我的意思是类是对象的根,类本身是Class的实例(之所以称为Metaclass,是因为其实例是类).我在一些博客中看到Class类的方法new的一些替代.

因此Class表现为类,但其实例是类.因此,似乎我们有一个圆圈,它看起来像是Class类是其自身的实例.

我在这里显然缺少一点.类Class的起源是什么?

这是一个使我感到困惑的例子:

class Class
  def new
    #something
  end
end

但是关键字class表示类Class的实例.那么,该如何工作?

解决方案

这是怎么工作的

简单:并非如此.无论如何,不​​是在Ruby中.

就像大多数其他语言一样,有些核心实体被简单假定为存在.它们从天上掉下来,在稀薄的空气中物化,神奇地出现.

在Ruby中,其中一些神奇的东西是:

  • Object没有超类,但是您无法定义没有超类的类,隐式直接超类始终为Object. [注意:可能有Object的实现定义的超类,但最终会有一个没有超类的类.]
  • ObjectClass的实例,它是Object的子类(这意味着间接地ObjectObject本身的实例)
  • ClassModule的子类,它是Class的实例
  • ClassClass
  • 的实例

这些东西都不能用Ruby来解释.

BasicObjectObjectModuleClass都需要同时存在,因为它们具有循环依赖性.

仅仅因为这种关系不能用Ruby代码表达,并不意味着Ruby语言规范不能说必须如此.由实现者来决定执行此操作的方法.毕竟,Ruby实现对您作为程序员没有的对象具有一定的访问权限.

例如,Ruby实现可以首先创建BasicObject,将其superclass指针和class指针都设置为null.

然后,它创建Object,将其superclass指针设置为BasicObject,并将其class指针设置为null.

接下来,它创建Module,将其superclass指针设置为Object,并将其class指针设置为null.

最后,它创建Class,将其superclass指针设置为Module,并将其class指针设置为null.

现在,我们可以覆盖BasicObjectObjectModuleClassclass指针,以指向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 always Object. [Note: there may be implementation-defined superclasses of Object, but eventually, there will be one which doesn't have a superclass.]
  • Object is an instance of Class, which is a subclass of Object (which means that indirectly Object is an instance of Object itself)
  • Class is a subclass of Module, which is an instance of Class
  • Class is an instance of Class

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆