第4回 継承(5月11日)

今日の課題

■ 継承

例題1

StarMorph クラスのサブクラスとして,「MyStarMorph」を定義しよう. MyStarMorphクラスは,星の位置を指定するメッセージ position: を受け取る と,指定された座標を Transcript に表示した後で,指定された座標に星を表 示する(通常の position メッセージと同一の動作)ように,メソッドをオー バライドしよう.

サブクラスは,以下の手順で定義する.

  1. システムブラウザを開ける.
  2. 「カテゴリ」のペインで「MyObjects」(今まで練習で作ってきたところ ならどこでも良い)を選ぶ.
  3. 「編集」のペインで,「Object subclass: #NameOfSubclass」の部分を 「StarMorph subclass: #MyStarMorph」と書き換え,「了解(s)」を選択する.

サブクラスのメソッドは,通常どおり定義する.position: をオーバーラ イドするが,具体的には以下のようにメソッドを定義する.
 position: pos
    Transcript show: pos.
    Transcript cr.
    super position: pos

MyStarMorph のインスタンスに,openInWorld のメッセージを送ると表示 される.マウスでつかんで移動させてみよう.また,position メッセージを 送ってみよう.
(Workspace)
s := MyStarMorph new openInWorld position: 100@100

MyStarMorph のメソッド定義は,position だけであるが,new や openInWorld のメッセージも処理できる.StarMorph のサブクラスであるため である.

■ クラスの階層の確認

システムブラウザには,クラスの階層「hierarchy」を確認する機能があ る.次の手順でシステムブラウザを操作してみよう.

  1. 「クラス」ペインの「MyStarMorph」を選択する.
  2. ブラウザの中段にある「hierarchy」のボタンを押す.
  3. すると,「Hierarchy Browser:MyStarMorph」という新しいウインドウが 表示される.

    このウインドウの上段には3つのペインがあり,それぞれ左から「クラ ス」,「プロトコル」,「メソッド」のペインである.

  4. 「クラス」のペインのスクロールバーを操作すると,MyStarMorph クラ スからみて,たくさんのスーパークラスが存在することがわかる.
  5. 上のほうに隠れている「Morph」を選択する.
  6. 右はしの「メソッド」のペインを操作して,メソッドを眺めてみると, 「position」や「position:」というメソッドがある.
  7. 「position:」を選択すると,メソッドの定義が参照できる.

■ ポリモーフィズム

オブジェクトに送るメッセージは同じでも,オブジェクトによって動作が 異なる.

例題2

以下のプログラムを Workspace 上で実行してみよう.最後の行を何 度も実行すると,どんな動作をするだろうか.
b := Bag new.
b add: (StarMorph new openInWorld position: 100@100).
b add: (MyStarMorph new openInWorld position: 100@130).
b do: [: s | s position: ( s position + 100 )]

C言語で同じプログラムを作ることを想像してみよう.

■ 第2回目小レポート

星の表示位置をファイルに記録すること,ファイルから読み込んだ位置に 星を表示すること,という2つの目的のプログラムを作れ.

ファイルに記録するためには,(1) 星のインスタンス s を生成する,(2) s に「record: ファイル名」のメッセージを送ると記録が開始する,(3)マウ スで星を動かす.すると位置を記録する,(4)「stop」のメッセージにより記 録を終了する,という手順を想定する.

ファイルからの読み込みのためには,(1) 星のインスタンスを生成する, (2)「play: ファイル名」のメッセージによりファイルから位置情報を1秒おき に読みとり表示をする.

作成したクラスMyStarMorphとメソッドrecord,stop,play,positionは, 前回の小レポートと同様に,ブラウザで表示させて,画面のスナップショット により印刷する.そして,今回は,メソッドの各行にコメントを手書きで記入 して動作を説明すること.なお,1画面に複数のブラウザを表示させて,印刷 枚数を少なくせよ.

表紙と実行結果は不要である.

ヒント1

座標をファイルに出力する例.
fout := FileStream forceNewFileNamed: 'position.dat'
fout nextPutAll: '100@110'; cr.   (プリントではコロンが抜けていました)
fout nextPutAll: '100@120'; cr.
fout nextPutAll: '100@130'; cr.
fout close

補足説明:座標は Point クラスである.100@123 は,Point のインスタ ンスを直接的に作るための書き方である.ファイルに出力するときは,Point のインスタンスは,文字列に変換する必要がある.'100@110'は 100@110 asString と同じである.

ヒント2

「record」メソッドでファイルストリームを書き出し用に生成する.その ストリームは,position メソッドやstopメソッドからも参照するので,イン スタンス変数でストリームを保持しておく必要がある.

たとえば,MyStarMorph のインスタンス変数に fout を追加する.

ヒント3

メソッド「record: ファイル名」において,FileStream の書き出し用の インスタンスを生成し,インスタンス変数 fout で保持しておくには,次のよ うにすればよい.
 record:  fileName
    fout := FileStream forceNewFileNamed: fileName

ただし,fout が nil でない場合は,既にファイルに書き出しをしている ところであるので,fout を close した後で,新しいファイルを開く.

ヒント4

メソッド「stop」は,ストリームを閉じる処理をする.重複して閉じない ようにする処理や,インスタンス変数の更新(fout := nil)することが必要 である.

ヒント5

メソッド「position」は,fout が nil のときは,Transcript に座標を 表示し,fout が nil でないならば,ストリームとみなして座標を書き出す.
 position: pos 
 ?? ( fout と nil を比較 )
 ?? もし nil のとき
 ??     [ Transcript に座標を表示 ]
 ?? もし nil でないとき
 ??     [ fout に座標を表示 ]
 ?? スーパークラスの position: を使って星を表示(プリントには抜けていました)

座標クラス Point のインスタンスは,asString で文字列に変換して おくこと.

ヒント6

メソッド「play」は,おおむね以下の形になっている.
 play: fileName 
 ?? 一時変数として,fin と line を宣言する.つまり |fin line|とする.
 ?? fin := 読み込み用で fileName のファイルを開く(ファイルストリームを作る)
 [fin atEnd]
     whileFalse: [(Delay forMilliseconds: 100) wait.
 ??      line := fin から1行読み込んだ文字列を ReadStream のインスタンスにする
         self position: (Point             (プリントでは、Position(大文字になっていました)
             x: (?? line より @文字の手前までを抽出)
             y: ?? line より残りの文字列を抽出 )].
 fin close

self position: (Point - - - が分りにくいと思うだろう.要するに,たとえば, self position 100@110 のように座標を指定しようとしている.100@110 とい う座標インスタンスは,Point x: 100 y: 110 とすれば生成できる.100 と 110 は,文字列の入ったストリーム line に '100@110'と入っているので,「文 字 @(つまり,$@)までを読み」そして「残りを読む」という処理をすれば 「100」と「110」が得られる.

ヒント7

Workspace 上では次のようにして,座標の記録をする.
s := MyStarMorph new openInWorld position: 100@100  (Alt-dを押す)
s record: 'test1.dat'   (Alt-dを押す)
星をマウスで,掴んで移動させては離し,掴んで移動させては離し,
を何度も繰り返す.
s stop  (Alt-dを押す)

引き続き,Workspace 上で次のようにすると,記録した通りに星が動く.
s play: 'test1.dat'


(C) 2006.5.2 by tokuhisa