为什么Metaclass的Metaclasses实例而不是Class?

时间:2010-12-10 21:52:52

标签: smalltalk pharo

我想知道为什么使用两个不同的类,而不是仅使用Class。

3 个答案:

答案 0 :(得分:5)

简短的回答是“您假设类是系统范围的类的实例是错误的,每个类实际上是类特定元类的实例”,并且“它不会以任何其他方式工作”。

对答案的略微修改是“名字真的令人困惑,有时候更容易记住他们的角色,而不是过多考虑他们的工作方式”。

短毛回答:

Metaclass是一个实例,就像所有其他普通的Smalltalk类一样,它需要它自己的专用类。常规Smalltalk对象的每个实例都有一个类,其继承遵循类层次结构。每个类本身都是类特定元类的实例,其继承遵循元类层次结构。每个元类本身都是Metaclass类的一个实例,它被虚拟机在一个简洁的小技巧中短路,因为没有人发现使用Metaclass类作为父类,并且所有尝试过的人一般都发现他们的理智在这个过程中开始腐蚀。

更长,仍然毛茸茸的答案:

Smalltalk允许每个类包含特定于类的消息。这些与Java中的静态方法大致相同 - 但有一些显着的差异。其中一个区别是Smalltalk类实际上是实例化对象 - 它们是系统中的活动对象,具有从其他对象继承的能力,并包含实例变量。

此属性导致系统中存在大量继承层次结构。常规对象每个都是一个Class的实例,消息发送到搜索对象类的对象,然后跟踪Class层次结构的继承链。发送到常规对象的消息将在类层次结构中解析。

此外,类对象是一个特定于类的Metaclass的每个实例。发送到类对象的消息通过查找特定于类的元类,然后在元类层次结构上向上解析。

再增加一层,元类对象每个都是系统范围内唯一的Metaclass类的实例。发送到元类对象的消息在系统范围内唯一的Metaclass中查找,不允许从任何人继承,并且硬连接为VM中的短路。

从技术上讲,系统有两个继承层次结构,第三个是短路伪造的。虽然有很多实际的理由,但没有理论上的理由停在两点。这允许每个对象拥有它自己的,对象唯一的消息,每个类拥有它自己,类唯一,消息,并强制所有元类只回答元类中定义的一组消息。

干净,呵呵?

答案 1 :(得分:3)

你显然需要一个类的两个ClassDescriptions:一个用于实例方法,一个用于类方法。

现在,您可能仍尝试为两个对象使用Class。我认为使用Metaclass的一个原因是你需要区分这两者。如果你看一下方法theMetaClasstheNonMetaClass,你会看到它们互相镜像:你通过thisclass成员从元类转到类,通过常规类指针从类转到元类(任何对象拥有)。如果它们都是实例类,它们无法知道它们实现哪一方 - 除非有一个标志槽,这比创建子类更糟糕。

答案 2 :(得分:1)

这是我完全理解的事情之一......直到我必须解释它;-)经过多次蒸馏......

假设:

  • 对象的行为由其类
  • 指定
  • 类也是对象
  • 常规对象/类具有仅对常规对象/类有意义的行为

因此,类和实例应该具有不同的行为说明符(即类)。

从另一个角度来看,我们称之为“实例端”的是的实例端。我们称之为“类侧”代表元类的实例端。

例如,Class定义了#addClassVarNamed:和#addInstVarNamed :,因为那些在实例端都有意义,Metaclass只定义了#addInstVarNamed :,因为没有类边类变量。

深入研究细节,请参阅“Pharo By Example”或“Smalltalk Programming Technique基础知识”