レッスン6

オブジェクトとそのメッセージ

【以下【】の中は訳者が付け足したものです。】

さて、 Rect クラスのオブジェクトを生成して、 実行すべきメソッドを選択できるよう、そのオブジェクトにメッセージを送りましょう。 Rect クラスのオブジェクトを生成するには、 その構文は、単に、クラス名の後に、そのオブジェクトにつけたい名前を書くだけです。 Rect クラスのオブジェクトで、名前を Box1 とすると、 ステートメントは、次のようになります。
Rect Box1
これだけです! このオブジェクトを生成することによって、あなたは新しいMopsワード" Box1 "を、メモリー内の辞書に追加したのです。 前のレッスンの Rect の定義を思い出して、 メモリー内のオブジェクトを視覚化すれば、こんな風になるでしょう。:
オブジェクトが生成されたとき、インスタンス変数のセル(小領域)にはゼロが置かれており、 そこにデータを入れる旨のメッセージをオブジェクトが受け取ったときの数値の保管場所となります。

プログラム中でMopsメッセージを打ち込むときには、そのメッセージは三つの部分を持ちます。: 引数、セレクター、レシーバー【メッセージの受け手】です。

引数(パラメター)はその演算操作に渡される数値です。 それらは、ちょうどレッスン 1での引数tぽ同じように、パラメタースタック上に置かれます。 もちろん、全てのメッセージが引数を持つとは限りません。 いくつかの演算操作は、それらに渡す数値を全く必要としません。

第二の部分セレクターは、実際には、あなたがそのオブジェクトに実行してもらいたい演算操作を含んでいるメソッドの名前です。 言い換えれば、そのオブジェクトが、そのクラスのどのメソッドを動かすのか"選択(セレクト)"するのです。; オブジェクトは、そのメッセージのセレクターを、そのオウジェクとのクラスにあるメソッドと照会します(もし、そのクラス自体の中になければ、スーパークラス階層を遡ります)。

メッセージの最後の部分であるレシーバーは、オブジェクトの名前でなければなりません。 "そのもの"に、あなたはセレクターで特定した演算操作を実行するよう要求するのです。 前レッスンで用いた会計士メタファーでは、レシーバーは、"確定申告手続をする"べき会計士の名前です。

Box1 は、私達の長方形クラスのオブジェクトなのですから、 それに対しては、 Rect クラスで定義されたメソッドの一つを選ぶメッセージを送ることができます。
300 20 400 100 put: Box1
座標300, 20 と 400, 100 を、 Box1 オブジェクト内の TopLeft と BotRight のために取り置かれたデータ小領域に格納しました。 結局、 Box1 のクラスの PUT: メソッドがすることは、これなのです。: 二つの引数からなる二つの集合をあるオブジェクトのデータ小領域に置くこと、です。

後になって、もしも Rect クラスの新しいオブジェクト, " Box5 "を生成したならば、 Box5 のデータ小領域は、初めは空っぽでしょう。 別の PUT: メッセージを Box5 に送って、 Box5 の座標をそのオブジェクトのデータ小領域に置かなければなりません。 このようにして、 オブジェクトはプライベートデータを保守管理するのです。

さて、 Box1 を用いてオブジェクトをスクリーン上に描画するためには、 もうひとつメッセージを送る必要があります。 Rect クラスの DRAW: メソッドを呼び出すものです。
draw: Box1
Rect クラスをあなたが頭から定義している場合には、 二つのメソッドの機能を一つにした、新しいメソッドを定義することもできるでしょう。 そうした場合には、一つのメッセージで、 PUT: と DRAW: の両方を手配してくれることでしょう。 これをするには、 その新しいメソッドが、同じクラスのメソッドを見つけ出すことができるようにする必要があります。 そのときには、 SELF という名前のメッセージレシーバーが便利になります。 この新たなメソッド( DISP: )を付け加えれば、クラス定義は次のようになります。:
:class  RECT  super{ object }
record
{ point    TopLeft
  point    BotRight
}

:m PUT:  ( l t r b -- )  put: BotRight   put: TopLeft  ;m

:m DRAW:  ^base  FrameRect  ;m

:m DISP:  ( l t r b -- )  put: self  draw: self  ;m

;class
DISP: メソッドはメッセージ ‘put: self’ および ‘draw: self’ を含んでいます。 ‘put: self’ メッセージは、"現在のオブジェクトに対して、このクラスの PUT: メソッドがすることを全部しなさい"ということを意味しています。 ‘draw: self’ についても同様のことがあてはまります。 もしも、これらのメッセージのどちらかが Rect のスーパークラスに属しているメソッドを捜すものであるなら、レシーバーは SUPER になります( ‘put: super’ という具合です)。

DISP: メッセージ内に ‘put: self’ メッセージがある場合、大事なことがあります。 DIPS: メソッドは、そのセレクターを含むどのメッセージも、4つの整数を渡してくることを期待します。これはまさに、実際に実施される PUT: メソッドと同じになります。それは、4つの整数を必要とする格納命令を実行するからです。 したがって、 Box1 のスクリーン上への配置と描画の両方をするには、次のようにメッセージを送らなければなりません。
12 10 100 50 disp: Box1
これを試してみたい場合には、イントロダクションでしたように、 Box1 を表示するためのウィンドウを持つ必要があります。 ですから、まず、(上の) Rect の定義をMopsウィンドウにコピーします (実際に同じように打つか、コピー&ペースト)。 それから、Mopsウィンドウ上の定義全体を(マウスをドラッグすることにより)選択します。 そして、Enterキーを押します。 この場合、コードはクラス定義ですから、 実行結果は、単に Rect クラスを定義するだけです。 何も起っていないように見えますが、 Rect の定義はMopsの辞書に入力され、 あなたの命令を待っている状態になります。

さて、次のように打ちこみましょう。:
Window ww
test: ww
Mopsウィンドウをクリックでフロントウィンドウに戻し、 Mopsウィンドウと ww の両方が見えるように、 適当に配置換えしてください。それから、次のコードを打ち込んで実行します。
Rect Box1
set: ww 12 10 100 50 disp: Box1
あなたの Rect インスタンス( Box1 )が、ウィンドウ ww 上に現れるはずです。

まとめ

次のステップに移る前に、要約して置きましょう。 Mopsプログラムの生成は、次のステップを含んでいます。: クラスを定義すること;そのクラスのインスタンスであるオブジェクトを生成すること。; そしてそれらのオブジェクトにメッセージを送ること。です。 クラス階層の構築はもっとも広いクラスから始まって、 より特殊なクラスの方へと、 サブクラスでそのスーパークラスの特性を継承しつつ、 作業は進められます。

ObjectStructure.png 右の図式は、この章で詳説したプログラム例の構造を見るのに役立つでしょう。 これは、上で論じたクラスとオブジェクトとの関係を、図形的に描いたものです。

このフレームワークで、メッセージ ‘12 10 100 50 disp: Box1’ を発行すれば、 その引数は、 Box1 が生成されたときとは逆順で Box1 のデータ小領域を埋めていきます。

そのデータの特性は、すでにインスタンス変数 TopLeft と BotRight で決められています。;これらインスタンス変数の各々の特性も、同じように、そのインスタンス変数 X および Y によって決められています。そしてこれらが今度は、その定義クラスである Int クラスのメソッドによって定義されています。

ですから、Mopsにおけるクラスとオブジェクトの関係は、多層的であることに気付くでしょう。 一方には、スーパークラスとサブクラスの関係があります。しかし、他方には、インスタンス変数とその定義クラスの関係もあります。 どちらの関係も、Mopsプログラムの階層を、それぞれ独立に流れ下っています。 このことは、上の例に後でさらにもうひとつ拡張を施したときには、もっと明確になるでしょう。

チュートリアルの目次へ
前へ < レッスン5 次へ > レッスン7


最終更新:2018年12月04日 08:40