みなさん、こんにちは。 今日の授業では
前にやった super について
理解しているか確認しようと思います。
しっかり考えてください。
理解しているかどうかテストします。
これで何を学ぶのかというと
super について
メッセージ探索について
そしてクラスメソッドについて 復習します。
1回の授業としては分厚い内容ですが 楽しんでください。
Dice クラスにメソッドを定義して
また、new メソッドを次のように 再定義するとします。
これがそのコードです。
inst := super new.
inst initialize. ^ inst
ここで、Dice new を実行すると
ここで問題です。
この表現式での inst は何でしょう？
super とは何でしょう？
super new とは何でしょう？
数秒の間に考えてみてください。
少しだけヒントをあげます。
今まで教えてきた経験からくるヒントです。
super はスーパークラスではありません。
そんな考えは頭の中から 追い出してください。
inst はスーパークラスのインスタンス ではありません。
そんなことになったら そのクラスのインスタンスを作れません。
では inst は何でしょう？
ちょっと掘り下げてみましょう。
super についての講義の中で
super はメッセージのレシーバーだと 言いました。
self と同様、super も メッセージのレシーバーを指します。
これは Pharo 特有の話ではありません。
Java や C# のような他の オブジェクト指向言語に共通したことです。
もちろん Smalltalk でも。
ここでメッセージは Dice new です。
レシーバーは何でしょう？ 構文的に言って、Dice ですね。
Dice クラスです。
これらのヒントを使って 考えてみてください。
では見てみましょう。
メッセージ探索の動作を憶えていますか？
インスタンスにメッセージを送ります。
例えば、色付きの矩形 （ColoredRectangle）に。
ColoredRectangle クラスに
そのメソッドが定義されているかを見ます。 定義されていません。
area は定義されていません。 ここにあります。
見つけた定義を適用します。
何に適用するのでしょう？ レシーバーにです。
これで、このメソッドが何をするのか わかります。
Dice class に new がないか探します。
探索して、Dice に適用します。
もっとよく見てみましょう。
前に説明した通り
Pharo では 1 回のメソッド探索で 1 回だけメッセージが送られます。
どんなオブジェクトであれ オブジェクトにメッセージを送ると
必ずそのクラスから探索します。 このリンクを辿るということです。
そしてこのリンクを辿っていきます。
常にこの 2 つのステップを踏みます。
どういうことかというと
前に言った通り super はレシーバーです。
レシーバーは Dice です。
したがって、Dice class の スーパークラスから new を探索します。
大事なのは、これは Dice class であって Dice ではないということです。
後で図で説明します。
新しい new を見つけたら
それをレシーバーに適用します。 レシーバーは Dice です。
new を Dice に適用すると
何をするのでしょう？
Dice の新しいインスタンスを生成して 初期化します。
inst は その新しいインスタンスになります。
ダイスです。
そしてそれを初期化して返します。
では図を見てみましょう。
new を Dice に送ると
どこを見るでしょう？ どのクラスを見るのでしょう？
Dice class を見ます。
ここに かの有名な new メソッドがあります。
そして何をするのでしょう？ super はどんなものだったかというと
super は Dice クラスです。 ここでのレシーバーです。
このオブジェクトに メッセージを送ります。
super は その式を持っているクラスの
スーパークラスから探す という指示です。
したがって、Dice class の スーパークラスを見ます。
ここを探索します。 そして上のほうを見ていきます。
するとどこかで
new が定義されています。
探索の結果
メソッドはここで定義されていて
そのメソッドをレシーバーに適用します。 Dice に適用します。
すると新しいインスタンスが得られます。 ここに書いておきます。
インスタンスが返ってきます。ダイスです。
そして inst は この新しいインスタンスを指します。
つまり、inst は新しいダイスです。
inst に initialize メッセージを 送って、そしてそれを返します。
この例題はゴチャゴチャとなりがちです。 回りくどいですからね。
ちゃんと理解しているかどうか判るように わざとそうしています。
2 つの事が混ざっています。
1 つは super です。
super という式を含むクラスの スーパークラスを見るということです。
super が指すのはレシーバーです。
2 つ目は、new です。 new はオブジェクトを生成するメソッドです。
この例ではこの 2 つが 組み合わさっていることで
理解するのが難しくなっています。
この授業を復習することをお勧めします。
とても重要な内容だからです。
繰り返しますが
super はメッセージのレシーバーです。
この場合、Dice です。
Dice クラスのスーパークラスから new メソッドを探します。
それをレシーバーであるDice に適用して インスタンスの生成をします。
いいですか？
まとめると、メッセージ送信は レシーバーのクラスからメソッドを探索します。
メッセージ送信のたびに探索を実行します。
Pharo でやることはそれだけです。 簡単ですね。
これで、super はその式を持つクラスの スーパークラスから探索するという
意味だということを理解できたはずです。
そして super はレシーバーであり レシーバーがクラスの場合もあります。
これで終わりではありません。 もう 1 つ問題があります。
Pharo を勉強するぐらいだから 何かに挑戦するのが好きですよね？
さあ、次の問題を考えてみましょう。
メソッドに super class
== self class と書いてあるとします。
この == はどういう意味かというと ポインタが同一かどうかの比較です。
意味としては
この super class で 得られるオブジェクトは
self class で得られるオブジェクトと 同一のものか、ということです。
このメソッドは true か false の どちらかを返します。
では問題です。
A new foo の結果は何でしょう？
A の新しいインスタンスを作って
foo メッセージを送ります。 つまりこのメッセージを評価します。
結果は何でしょう？その理由は？
答えは自分で考えてみてください。 私から正解は教えません。