カウンターで練習してみる
動かない
C.ioとして、下記ファイルを保存。
C := Object clone do ( n := 1 count := method(n := n + 1) asString := n asString ) c := C clone
コマンドラインから使ってみる。
Io> doFile("C.io") ==> 1 Io> c ==> 1 Io> c count ==> 2 Io> c ==> 1 Io> c n ==> 1
動かない。
上記定義では、"n + 1"でいう"n"は"c n"を参照するが、左側の"n"はメソッド実行時に新たに生成されるローカルオブジェクトにスロットnを作成して、"n + 1"をセットする。だから、カウントアップされたnはローカルオブジェクトにのみ保存され、メソッド終了と共に捨てられる。結果、"c n"は更新されない。
countのメソッドを修正してみる
C := Object clone do ( n := 1 count := method(self n := n + 1) asString := n asString ) c := C clone
コマンドラインから使ってみる。
Io> doFile("C.io") ==> 1 Io> c ==> 1 Io> c count ==> 2 Io> c ==> 1 Io> c n ==> 2
内部のnはカウントアップされてるみたいだけど、表示が上手くいかない。
上記定義では、"self n"と指定することによって、self = cが持つスロットnにセットしましょうと明示すれば、"c n"がカウントアップされる。
こうすると、countが最初に呼ばれるまでは、"c n"によって、プロトである"C n"が参照されるが、countが呼ばれることによって、その処理ではcにnスロットを作成し、以降は"c n"によってcが持つnスロットが呼ばれることになる。
ここでちょっとイヤらしいのが、↓。
count := method(n = n + 1)
こう書いても動く。
このとき、左のnとしてself nを探し当てる。"="は"upadteSlot"だけど、自身に該当するスロットが無い場合でも、プロトオブジェクトのスロットを更新せずに、自身にそのスロットを作成して値を設定する。
asStringを修正してみる
C := Object clone do ( n := 1 count := method(self n := n + 1) asString := method(n asString) ) c := C clone
コマンドラインから使ってみる。
Io> doFile("C.io") ==> 1 Io> c ==> 1 Io> c count ==> 2 Io> c ==> 2 Io> c n ==> 2
動いた!
asString := n asString
では、これが実行された時点でのn、つまり"1"がasStringとしてセットされるため、nが2,3,...と変わっても、asStringの内容は"1"のままとなる。そこで、
asString := method(n asString)
とすることによって、呼ばれた時点でのnを参照することができる。