StarMorph クラスのサブクラスとして,「MyStarMorph」を定義しよう. MyStarMorphクラスは,星の位置を指定するメッセージ position: を受け取る と,指定された座標を Transcript に表示した後で,指定された座標に星を表 示する(通常の position メッセージと同一の動作)ように,メソッドをオー バライドしよう.
サブクラスは,以下の手順で定義する.
サブクラスのメソッドは,通常どおり定義する.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」を確認する機能があ る.次の手順でシステムブラウザを操作してみよう.
このウインドウの上段には3つのペインがあり,それぞれ左から「クラ ス」,「プロトコル」,「メソッド」のペインである.
オブジェクトに送るメッセージは同じでも,オブジェクトによって動作が 異なる.
以下のプログラムを 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つの目的のプログラムを作れ.
ファイルに記録するためには,(1) 星のインスタンス s を生成する,(2) s に「record: ファイル名」のメッセージを送ると記録が開始する,(3)マウ スで星を動かす.すると位置を記録する,(4)「stop」のメッセージにより記 録を終了する,という手順を想定する.
ファイルからの読み込みのためには,(1) 星のインスタンスを生成する, (2)「play: ファイル名」のメッセージによりファイルから位置情報を1秒おき に読みとり表示をする.
作成したクラスMyStarMorphとメソッドrecord,stop,play,positionは, 前回の小レポートと同様に,ブラウザで表示させて,画面のスナップショット により印刷する.そして,今回は,メソッドの各行にコメントを手書きで記入 して動作を説明すること.なお,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 と同じである.
「record」メソッドでファイルストリームを書き出し用に生成する.その ストリームは,position メソッドやstopメソッドからも参照するので,イン スタンス変数でストリームを保持しておく必要がある.
たとえば,MyStarMorph のインスタンス変数に fout を追加する.
メソッド「record: ファイル名」において,FileStream の書き出し用の インスタンスを生成し,インスタンス変数 fout で保持しておくには,次のよ うにすればよい.
record: fileName fout := FileStream forceNewFileNamed: fileName |
ただし,fout が nil でない場合は,既にファイルに書き出しをしている ところであるので,fout を close した後で,新しいファイルを開く.
メソッド「stop」は,ストリームを閉じる処理をする.重複して閉じない ようにする処理や,インスタンス変数の更新(fout := nil)することが必要 である.
メソッド「position」は,fout が nil のときは,Transcript に座標を 表示し,fout が nil でないならば,ストリームとみなして座標を書き出す.
position: pos ?? ( fout と nil を比較 ) ?? もし nil のとき ?? [ Transcript に座標を表示 ] ?? もし nil でないとき ?? [ fout に座標を表示 ] ?? スーパークラスの position: を使って星を表示(プリントには抜けていました) |
座標クラス Point のインスタンスは,asString で文字列に変換して おくこと.
メソッド「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」が得られる.
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' |