こんにちは。継承とメソッド探索の 第 4 講へようこそ。
アルゴリズムがメソッドを見つけられなかった 場合に何が起こるのかを学びます。
この講義で
メソッドが見つからず
メッセージを理解できなかった という事実を扱う処理を
クラスのコードで追加する方法が わかるようになります。
メッセージ送信を簡単に復習しましょう。
area メッセージが ColoredRectangle に 送られます。
まず、アルゴリズムは メッセージにマッチするメソッドを探します。
レシーバーのクラスからメソッドを探し始めます
area が ColoredRectangle で見つかったら それを実行します。
しかし area が見つからなければ アルゴリズムはスーパークラスを探します。
Rectangle で area が見つかります。
そのメソッドが レシーバーの上で実行されます。
area メソッドが全く存在していない場合には 何が起こるでしょうか？
探索が失敗したらどうなるのでしょうか？
ここに例題があります。 coucou: メッセージが オブジェクト node 1 に送られます。
coucou: は階層の中にありません。
coucou: メッセージが node 1 に送られます。
アルゴリズムは Node で coucou: を 見つけることに失敗します。
次に、Object を探します。 coucou: はありません。
この時点で
Pharo のバーチャルマシンが doesNotUnderstand: メッセージを
レシーバーの node 1 に送ります。
DNU とは Does Not Understand です。
バーチャルマシンはメッセージを 引数に変換します。
これがその引数です。 「coucou: stef」
もう一度、ステップを追っていきます。
coucou: が node 1 に送られます。 そのクラスでマッチが試みられて
そしてスーパークラスで試みられます。
coucou: は見つかりません。 そこでメッセージ doesNotUnderstand: が
オブジェクト node 1 に再送されます。
アルゴリズムは doesNotUnderstand: メソッドを
node 1 のクラスで探します。
見つかりません。 アルゴリズムはそのスーパークラスから探します。
ここにあります。
doesNotUnderstand: メソッドが Object で見つかり、実行されます。
つまり
Object のあらゆるサブクラスで
doesNotUnderstand: を実装して
メッセージを理解できなかった場合の 特殊な振る舞いを
起こすことができます。
このスライドにその詳細を
ステップ毎に示しています。
doesNotUnderstand: は他のメッセージと同様に メッセージです。
したがって、 DoesNotUnderstand: メソッドを実装して
インスタンスがメッセージを理解できなかった時に 実行させることができます。
このメカニズムは
面倒な処理、たとえば
プロキシや自動移譲のような
あるオブジェクトが受け取ったメッセージを全て
他のオブジェクトに送りたい時に使います。
doesNotUnderstand 機構は そんなことに使われます。
doesNotUnderstand:の デフォルトの実装は
Object クラスにあります。
その実装では例外を上げます。
その例外は
MessageNotUnderstood と呼ばれます。
したがって、もしも Object クラスの DoesNotUnderstand: メソッドが実行されたら
例外が上がります。
つまりコードの中でその例外をキャッチできます。
他の例外のキャッチと同じ方法で。
例外は、理解されなかったメッセージの デバッガーを開きます。
この例では
また Node クラスに戻りますが
sayHello メソッドが Node にあって coucou: メッセージを
レシーバーつまり self に送ります。
また、 welcome メソッドもあって
sayHello メッセージを self に送ります。
welcome メソッドでは 理解されなかったメッセージのコンテキストで
特殊なハンドリングをします。
もしメッセージが理解されなければ ハンドルされます。
ここで、 sayHello が coucou: メッセージを self に送ります。
coucou: はまだ未実装です。
最終的に doesNotUnderstand: メソッドが
実行されます。
MessageNotUnderstood 例外が 上げられます。
on:do: と続くこのコードが
例外をキャッチするのに使われます。 Java の try/catch に似ています。
このコースの続く講義で これらの例外について学びます。
ここで重要なことは このコードが
Java の catch と同じで 例外に対して実行されるということです。
さあ、メッセージ welcome を
node 1 に送ります。
coucou: が実装されていないことが 判明して
コンソールに「Something went wrong with the message.」と表示されます。
これまででわかったことは
探索アルゴリズムがメッセージにマッチした メソッドを見つけられなかった時には
doesNotUnderstand: メッセージが 元のレシーバーに送られて
元のメッセージが引数として渡されます。
どんなクラスでも このメソッドを定義できます。
Object クラスでのデフォルトの実装が 実行されると
例外が上がります。
MessageNotUnderstood 例外です。
この例外をコードでキャッチすることも
デバッグすることもできます。