id:m-hiyama:20080109:1199863428 を Squeak Smalltalk で


なにかいろいろと大事なポイントをハズしてしまっているような気もするのですが、ひるまずに。


図は、赤矢印が継承関係、黒矢印がクラス-インスタンス関係です。


http://squab.no-ip.com/collab/uploads/61/metaclass.png

Object subclass: #Person
    instanceVariableNames: 'name'

Person class >> named: nameString
    ^self new name: nameString; yourself

Person >> name: nameString
    name := nameString
| s1 s2 p |
s1 := 'Hello'.
s2 := 'Bye-bye'.
p := Person named: 'tonkichi'.

"  1  "  self assert: [ByteString allSuperclasses includes: Object].
         self assert: [(ByteString class) allSuperclasses includes: Object class].
"  2  "  self assert: [Person superclass == Object].
         self assert: [(Person class) superclass == Object class].
"  3  "  self assert: [Metaclass allSuperclasses includes: Object].
         self assert: [(Metaclass class) allSuperclasses includes: Object class].
         self assert: [(Object class)  allSuperclasses includes: Object].
"  4  "  self assert: [s1 class == ByteString].
"  5  "  self assert: [s2 class == ByteString].
"  6  "  self assert: [p class == Person].
"  7  "  self assert: [(ByteString) class == ByteString class].
         self assert: [(ByteString class) class == Metaclass].
"  8  "  self assert: [(Person) class == Person class].
         self assert: [(Person class) class == Metaclass].
"  9  "  self assert: [(Object) class  == Object class].
         self assert: [(Object class) class == Metaclass].
" 10  "  self assert: [(Metaclass) class == Metaclass class].
         self assert: [(Metaclass class) class == Metaclass].

^'OK'


檜山さんの Java を模した例からするとちょっとややこしいのですが、Smalltalk で、あるオブジェクトが属するクラスのクラスオブジェクトを得るのには #getClass() ではなく、#class というメソッドをコールします。また、すでにクラスはすべて一階に落とし込み済みなので、クラス名はそのままクラスオブジェクトとして参照可能です(したがって .class の有無による両者の区別は無用)。スーパークラスへのアクセスは #superclass を用います。


Smalltalk今は三階 四階 建てです。つまり、檜山さんの例のように CLASS(あるいはそれを下階へ落とし込んだ Class )ひとつではなく、それぞれのクラスひとつにひとつづつにそれが属するクラスがあり、それをメタクラスと呼びます。メタクラスは原則として無名ですが、便宜的に「クラス名 class」と呼称します。ただこれは、メタクラスオブジェクトを得る式でもあるので、上のスクリプトでは紛らわしさを軽減するために式のほうは「(クラス名) class」、メタクラス自身を指すときは「クラス名 class」としてあります。

メタクラスは互いに、各々に属するクラスの継承関係を自身たちも模した継承関係にあります。つまり、ByteString や Person が Object のサブクラスであるように、ByteString class や Person class は Object class のサブクラスです。


メタクラスもオブジェクトなので属するクラスを持ちます。Smalltalk では Metaclass というクラスがそれで、すべてのメタクラスは Metaclass のインスタンスです。Metaclass もクラスなので Metaclass class というクラスに属しますが、これはメタクラスでもあるので Metaclass のインスタンスです。二階 三階 建てのときに Class が自身のインスタンスである「ループ」は、 Metaclass と Metaclass class が互いに互いのクラスでありインスタンスであるというかたちで現れます。