为了账号安全,请及时绑定邮箱和手机立即绑定

Ruby元类混淆

Ruby元类混淆

叮当猫咪 2019-11-02 10:46:47
我知道ruby中的所有类都是元类Class的实例。而“常规”对象就是这些类的实例(元类Class的实例)。但是我一直在想,我的意思是类是对象的根,类本身是Class的实例(之所以称为Metaclass,是因为其实例是类)。我在一些博客中看到newClass 的method的一些重载。因此,Class表现为类,但其实例是类。因此,似乎我们有一个圆圈,看起来类Class是其本身的实例。我显然在这里漏了一点。类Class的起源是什么?这是一个使我感到困惑的示例:class Class  def new    #something  endend但是关键字class暗示了Class类的一个实例。那么这是如何工作的呢?
查看完整描述

3 回答

?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

这项工作如何


简单:并非如此。无论如何,不是在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,我们就大功告成了。


从系统外部很容易做到这一点,从内部看起来却很奇怪。


但是,一旦它们确实存在,就完全有可能在纯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运行时系统也必须提供某些东西。


查看完整回答
反对 回复 2019-11-02
?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

是的,Class是其自身的实例。它是Module的子类,也是类的实例,而Module是Object的子类,也是Object的实例。它确实是相当循环的-但这是核心语言的一部分,而不是库中的任何内容。当我们编写Ruby代码时,Ruby运行时本身没有相同的限制。


不过,我从来没有听说过用“元类”这个词来谈论类。在Ruby中根本没有使用它,但是当它被使用时,它通常是正式称为“对象的单一类”的同义词,这是一个比Object-Module-Class三角形更令人困惑的主题。


查看完整回答
反对 回复 2019-11-02
?
杨魅力

TA贡献1811条经验 获得超5个赞

“扭曲”链接给出了元圆度。它是从根的本征Class类到类的内置超类链接。这可以表示为


BasicObject.singleton_class.superclass == Class

了解该.class映射的一个线索是看到该映射是从本征类和超类链接派生的:对于一个对象x,x.class是本x征类的超类链中的第一个类。这可以表示为


x.class == x.eigenclass.superclass(n)

其中eigenclass的“概念别名” singleton_class (可抵抗带有立即值的问题),y.superclass(i)表示i-th的第超类,y并且n是的最小x.eigenclass.superclass(n)类。等效地,x.eigenclass将跳过的超类链中的本征类(请参见rb_class_real,这也表明在MRI中,甚至superclass链接都是间接实现的-它们是通过跳过“ iclasss ” 而产生的)。这导致class每个类别(以及每个本征类别)的始终是该Class类别。


一种图象是通过提供该图。


元类的混乱有两个主要来源:


闲话。Smalltalk-80对象模型包含概念上的不一致性,这些不一致性已由Ruby对象模型纠正。此外,Smalltalk文献在术语中使用辩证法,不幸的是,在Ruby文献中尚未对此进行充分补救。


元类的定义。目前,该定义指出元类是class的类。但是,对于所谓的“ 隐式元类 ”(在Ruby和Smalltalk-80的情况下),更合适的定义是类的元对象。


查看完整回答
反对 回复 2019-11-02
  • 3 回答
  • 0 关注
  • 578 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信