- 起点指定なし
ローカル変数 → 自オブジェクトのプロパティ → プロトタイプのプロパティ → ・・・
→ ルートオブジェクトのプロパティ - self 起点
自オブジェクトのプロパティ → プロトタイプのプロパティ → ・・・
→ ルートオブジェクトのプロパティ - 特定オブジェクト 起点
指定オブジェクトのプロパティ → プロトタイプのプロパティ → ・・・→
ルートオブジェクトのプロパティ
t1 = Turtle ! create. t1:value = "T1". t1:test = [ | ; value | value = "local". TextField ! (value) create. TextField ! (self:value) create. ]. t1 ! test.
local T1
「value」で指定した場合はローカル変数の値、「self!value」で指定した場合には t1 オブジェクトのプロパティ値が参照されている。
変数/プロパティ値が undef の場合
上のコードで 「value = "local".」を除去すると「value」の取得値は undef になる。
t1 = Turtle ! create. t1:value = "T1". t1:test = [ | ; value | TextField ! ("(" + (value) + ")") create. TextField ! ("(" + (self:value) + ")") create. ]. t1 ! test.
([undef]) (T1)
ローカル変数の定義自体もなくなれば、「value」の値は t1 のプロパティを参照することになる。
... t1:test = [ ...
(T1) (T1)
つまり、値が undef であっても 変数が見つかればその時点で上位のスコープへの探索は停止する。
プロパティも同様の動きになる。
t1 = Turtle ! create. :value = "T1". t1:test = [ TextField ! ("(" + (self:value) + ")") create. ]. t1 ! test.
(T1)
t1 = Turtle ! create. :value = "T1". t1:value = undef. t1:test = [ TextField ! ("(" + (self:value) + ")") create. ]. t1 ! test.
([undef])
t1 に プロパティ value が定義されていなければルートの value 値が参照されるが、 t1:value に undef が設定されていると t1:value が採用される。
メソッドの場合
メソッドの探索もプロパティを同じ探索ルールになる。
t1 = Turtle ! create. t1:test = [ TextField ! "T1" create ]. t2 = t1 ! create. t2 ! test.
T1
t2 に メソッド test が定義されていないので、プロトタイプである t1 の test メソッドが実行される。
t1 = Turtle ! create. t1:test = [ TextField ! "T1" create ]. t2 = t1 ! create. t2:test = undef. t2 ! test.
エラーがあります。"test" という命令が見つかりません。
今度は t2 に test が定義されていて値が undef なので命令が見つからないというエラーになっている。
メソッド探索もプロパティ値と同様に値が undef でも定義があった時点で探索が停止する。
メソッドの上書きと上位メソッドの呼び出し
Turtle の forward など既定のメソッドを上書きする際、上書きしたメソッド内からプロトタイプの メソッドを呼び出すために同名のローカル変数を定義するのが常套手段になっている。
t1 = Turtle ! create. t1:forward = [ | n ; forward| ! 10 circle. ! (n) forward. ]. t1 ! 100 forward.
上記のコードで、forward 動作を上書きして「円を描いてから既定の forward 動作をする。」という動きになる。
この動作の意味を考えてみる。
これまでのパターンだとローカルに forward の定義があるので、 t1:forward 定義中に forward 命令を実行しようとした段階で forward 命令がない、ということでエラーになるはず。
同じことを独自メソッドでやってみよう。
t1 = Turtle ! create. t1:test = [ TextField ! "T1" create ]. t2 = t1 ! create. t2:test = [ | ; test | ! test. TextField ! "T2" create ]. t2 ! test.
forward の時と同じだとすれば、t2:test の定義中の !test で t1 の test が呼ばれるはず。
しかし結果は、「"test" という命令が見つかりません。」というエラーになる。
既定のメソッドと独自メソッドでは探索ルールが違うということなのだろうか?
わからない・・・
0 件のコメント:
コメントを投稿