こんにちは 今回の講義はとても高度なものです。
Pharo がどうやって
クラスとインスタンスの関係を 整理しているかを見ていきます。
これは本当に「好きな人」向けです。
習得することは必須ではありません。 実際、知らなくても Pharo を使っていますよね。
どうやって動いているのか知らなくても Pharo でプログラムすることはできます。
しかし、それを講義で説明されなければ 不満な人もいることでしょう。
new がどこで定義されていて
メタクラスのクラスは何なのか といったことです。
このビデオでは そういったことを説明します。
すぐに理解できなくても問題ありません。
しかし、もし面白そうだと思ったら
何度も見返してみてください。
根源的なことが そこに見つかるはずです。
このスライドで説明します。
この Mooc で何度も繰り返している
大事な概念です。
オブジェクトにメッセージを送ると
インスタンス関係のリンクを辿って そのオブジェクトのクラスでメソッドを探索します。
もしそこになければ 継承を辿っていきます。
探索は常にクラスでスタートして 継承を辿っていきます。
このルールはシステマチックに適用されます。
メタクラスの説明は
7 つの簡潔なポイントに まとめることができます。
あらゆるオブジェクトは クラスのインスタンスです。
難しいですか？ この例を見てみましょう。
このオブジェクトは OrderedCollection クラスのインスタンスです。
ここまではいいですね？
2 つ目のポイントです。あらゆるクラスは Object クラスから継承しています。
ここにあるように
OrderedCollection などは つまるところ Object から継承しています。
ここで言葉の補足ですが
eventually というのは 結局、つまるところ、ということです。
ややこしいですね。
つまり
継承関係のグラフは例外なく Object に繋がっているのです。
Object の責任は何でしょう？ Object は全てのオブジェクトが共通して
持っている振る舞いを表します。 エラー処理や
halt（停止）や announcement（通知）などです。
Object は継承の木の根です。
その責任は、最低限の振る舞いです。
リストに戻りましょう。 あらゆるクラスはメタクラスのインスタンスです。
以前のクラスでこれを説明しました。
クラス X は X class という名前の メタクラスのインスタンスです。
OrderedCollection クラスは
OrderedCollection class クラスの インスタンスです。
SequenceableCollection クラスも 同じ法則が成り立ちます。
Object クラスも Object class クラスのインスタンスです。
全てのクラスは 名前の最後に「class」がくっついた
それぞれ別のメタクラスの インスタンスです。
メタクラスはクラスを作った時に
自動的に作られます。
クラスを作る時にはメタクラスに new メッセージを送っています。
次のポイントにいきます。
メタクラスの階層は クラス階層と平行しています。
先ほど、OrderedCollection は
そのクラスのインスタンスだと 説明しました。
SequenceableCollection も 同様だと。
そこで それら 2 つの関係を定める必要があります。
ここに継承関係がある以上は こちらにもあるはずです。
どんな場合にも。
それが、2 つの平行した階層があると いうことの意味です。
この階層はいつ使うのでしょう？
OrderedCollection に new メッセージを送ると
どこから探索するでしょう？ OrderedCollection のクラスからです。
new が定義されているかどうかを 各クラスに尋ねていきます。
上にあがっていきながら new が定義されているか尋ねていきます。
ここで最初に示したポイントを利用します。
メッセージを送ると クラスから始めて継承を辿ります。
ここまでは
明快でしょう。 しかし、疑問が浮かび上がります。
Object class は 何のインスタンスでしょう？
悩むところです。
Object class の スーパークラスは何でしょう？
メタクラスにメッセージを送っても よいのでしょうか？
さらに、ここの何かしらに メッセージを送るのは？
見てみましょう。
あらゆるメタクラスは Class クラスから継承しています。
元は Behavior クラスです。
では最初の疑問に答えてみましょう。
Object class はクラスです。 Class から継承しています。
Class は ClassDescription や Behavior から継承しています。
Pharo と違って Lisp のような他のシステムでは
これら 2 つの要素は単体のクラスです。
Pharo では 再利用のために分割してあります。
Metaclass が ClassDescription を継承して
ClassDescription を両方で 利用できるようにしています。
Behavior は クラスの必須の部分を表現していて
Object から継承しています。
つまり、ここにメッセージを送ると
ずっとここまで辿ってきます。
クラスレベルの継承を辿ります。
では new がどこで定義されているのか？
インスタンスを生成する new メソッドは Behavior で定義されています。
OrderedCollection に new を送ると何が起こるのかというと
まず、そのクラスでメソッドを探索します。
new が継承の中で 再定義されていないとすると
スーパークラスを辿って探していきます。
new を見つけるまで。
メソッドを探索して レシーバ上で実行します。
つまり、ここで new メソッドを見つけて レシーバである
OrderedCollection クラスで実行します。 OrderedCollectionがインスタンスを生成します。
例えば 3 4 です。
いいですね？
今まで説明したポイントを使っています。
レシーバーのクラスから継承を辿って 探索していきます。
Behavior を一言で説明すると
インスタンスを持つオブジェクトの エッセンスです。
インスタンスを持つオブジェクトは
スーパークラスへのリンクや メソッド辞書や
インスタンスのフォーマットや 例に示したような
new や basicNew や new: などの メソッドもです。持たなければなりません。
new と basicNew の違いは
basicNew は決して再定義してはならない ということです。
メソッドについての講義で説明した通り
basic で始まるメソッドは 再定義しません。さもないと
元のメソッドに アクセスできなくなってしまいます。
コンパイル済みメソッドにアクセスする方法は ここに示す通り、他にも色々あります。
Behavior はクラスのエッセンスです。
ClassDescription は何でしょう？
Class と Metaclass に共有される 抽象クラスで
Behavior にいくつかの機能を加えます。
インスタンス変数の名前付けなどです。 Behavior までは人が関わらない実行でしたが
ClassDescription はそういう機能を 追加しています。
カテゴリーによる組織化というのは ブラウザで表示するプロトコルです。
例えば、メソッドを printing プロトコルに 格納することができます。
また、名前に関することです。
チェンジセットの管理や チェンジファイルの保存です。
自分で見てみてください。
このクラスは Class と Metaclass で 共有するためにあります。
Class の責任は
Pharo にあるクラスを表現することです。
クラス変数の表現や
名前付けやコンパイルを含みます。
もう一度言いますが コードを読んでください。
クラスはメタクラスのインスタンスです。
Object は Object class という名の クラスのインスタンスで
OrderedCollection についても同様で
Class や Class Description や Behavior にも同様に適用されます。
したがって、Class は Class class のインスタンスです。
そして ClassDescription は ClassDescription class のインスタンスです。
Behavior も同様です。
継承も見ていく必要があります。
これら 2 つの間に 継承関係があるのならば
右側にも同じ関係があります。
ここを見てわかるように 継承を辿ることができます。
したがって、Behavior class は Object class を継承します。
では、最後から 2 番目のポイントです。
あらゆるクラスはメタクラスのインスタンス だとすると、疑問が 1 つ浮かび上がります。
OrderedCollection class は 何のインスタンスなのでしょう？
Pharo はすべてのものはオブジェクトなので
OrderedCollection class は メタクラスのインスタンスです。
Object class と Class class は メタクラスのインスタンスです。
システム中の全てのメタクラスは Metaclass のインスタンスです。
さらに、Metaclass は ClassDescription から継承しています。
インスタンスが 1 つしかない 特殊なクラスです。
そのインスタンスには名前がありません。 名前はそのまたインスタンスが定義します。
荒っぽいように見えるかもしれません。
そういうわけで OrderedCollection は
OrderedCollection classのインスタンスで 名前が付けられています。
全てのメタクラスは Metaclass の インスタンスです。
コードでのメタクラスの主な責任は
その唯一のインスタンスを 生成し初期化することです。
残された質問は 1 つです。
Metaclass は 何のインスタンスでしょう？
Metaclass は OrderedCollection 同様 クラスなので
Metaclass class というクラスの インスタンスです。
Metaclass が ClassDescription から 継承していることはお分かりでしょう。
したがって Metaclass class は ClassDescription class から継承します。
OrderedCollection が Object から継承することから
OrderedCollection class は Object class から継承するように。
Metaclass は Metaclass class のインスタンスです。
OrderedCollection は OrderedCollection class のインスタンスで
Metaclass class は Metaclass のインスタンスです。
Class class や Object class が Metaclass のインスタンスであるように。
このループは奇妙に見えるかもしれませんが 文脈がわかれば納得がいきます。
Pharo を使う上で必要な知識ではないので スルーして結構です。
しかし、このグラフからわかるように
これまで話してきたポイントは 完璧に動作します。
オブジェクトにメッセージを送るたびに そのオブジェクトのクラスを見て
継承の木を見ます。 これらの例に示された通りに。
このインスタンスにメッセージを送れば Object に辿り着きます。
クラスにメッセージを送れば
メタクラスへ行って 継承を辿ります。
メタクラスにメッセージを送れば どこを見ればいいでしょう？
Metaclass です。 メタクラスは Metaclass のインスタンスです。
インスタンス関係のリンクを辿ります。
これはメッセージが理解できない場合や Object でのみメソッドが定義されている場合です。
では Metaclass にメッセージを送ると
どこを探索するでしょう？
まず Metaclass class から探して そこから継承を辿ります。
それで、…おっと！
もっとややこしいことになります。
同様に、Metaclass class に メッセージを送ると
あるいは OrderedCollection class に メッセージを送ると
Metaclass class のクラス
つまり Metaclass を見ます。
OrderedCollection class の場合も同様に この経路を辿ります。
このグラフは全体にわたって論理的である ことがわかるでしょう。
グラフが不整合してはいけません。
仮想機械（VM）は1つのことしかしません。
クラスからメッセージを探して 継承を辿ります。
この普遍的なグラフはそのプロセスにおいて 一貫性を持っています。
これは本当にすごいことだと思います。 私自身、これを疑問に思っていました。
では、まとめると、クラスはオブジェクトで メッセージを受け取ることができます。
手続きは全てのオブジェクトについて 同じものです。
メタクラスは 単一のインスタンスを持ち
明示的な名前を持っていません。
しかし、このことを知っていることは 必須ではありません。