ObjPtrはクラスではありません。その名から察せられる通り、オブジェクトのポインタなんですが、一種の変数です。変数に直接メッセージを送ってコンパイルできるというのが特徴です。実行されるまでに、その変数に、そのクラスのオブジェクトのアドレスが格納されていれば良い、というわけです。この変数を使った場合には、メッセージのバインディングはEarly Bindになります。
ObjPtrは宣言で作り出す変数です。メッセージがEarly Bindということは、コンパイル時にはメソッドが具体的に特定されるわけですから、ObjPtrは、少なくともメッセージバインドをコンパイルする時点までにはクラスが特定されていなければなりません。クラスの特定は、宣言時にする方法と、もっと後でする方法があります。
宣言時に、例えば、String(文字列)クラスにするには次のようにします。
ObjPtr myObjPtr class_is String
"myObjPtr"というのが生成されたオブジェクトポインタで、Stringクラスに設定されているということです。つまり、宣言の後に、"class_is"というワードを書いて、その後に設定したいクラスの名前を書けばよいわけです。上のようにおけば、"myObjPtr"にメッセージを送るコードは、"String"クラスのメソッドにバインドされます。
"class_is"以降をつけずに単純に宣言することもできます。
ObjPtr myObjPtr
このようにした場合はクラスは不定ですから、"myObjPtr"へのメッセージをコンパイルするより前に、クラスを設定しなければなりません。
後からクラスを設定するには次のようにします。
' myObjPtr set_to_class aClass
つまり、"set_to_class"というワードを使って設定するわけで、スタックにはオブジェクトポインタのXT(エグゼキューショントークン)、後に設定したいクラスの名前を書くということです。この設定の後は、"myObjPtr"へのメッセージは、このクラス(aClass)のメソッドがバインドされます。
コンパイルは実際のオブジェクトポインタの格納なしに実行できますが、実行時には本当のオブジェクトがないといけません。適切なクラスのオブジェクトのアドレスを格納しましょう。例えば、Stringクラスとすれば
String myString
.....
addr: myString -> myObjPtr
つまり、ワード"->"を使ってスタックから格納するということです。こうすれば、"myObjPtr"に関してバインドされたメソッドは"myString"に対して実施されるわけです。コンパイル状態でも書き方は同じです。なお、オブジェクトは、その名前を書けば普通はアドレスがスタックに積まれることになっていますから、"addr:"は省略できることが多いでしょう。
補足
なお、アレイクラスなど、宣言時にアイテム数をスタックに置く必要のあるクラス(Mopsマニュアル参照)でも、ObjPtrの宣言ないしクラスセット時には、アイテム数は必要ありません。格納されるオブジェクトのアイテム数が使われます。ただし、限界外の番号でアクセスしようとするともちろんエラーになりますが、コンパイルはできてしまうので、注意しましょう。
ObjPtrはMopsの古典的な機構です。おそらく実行速度を重視した設計なのだと思いますが、エラーチェックがほとんどない、つまり、少し危険な造りになっているようです。具体的には、ObjPtrについて指定されたクラスと異なるクラスのオブジェクトのアドレスを登録しても、エラーになりません。これをやってしまうと、実行時には、違うクラスのオブジェクトに直接メソッドを適用することになりますから、ほぼ間違いなく、クラッシュします。また、ObjPtrにオブジェクトのアドレスを格納することを忘れてメソッドを実行してしまうと、そのままクラッシュしてしまいます。実行前に捕まえてエラーを吐くという機構は無いようです。"set_to_class"を使った事後のクラス設定は、一旦セットされた後に、違うクラスにセットすることもできます。論理的にいえば、メッセージはコンパイル時にバインドされてしまうわけですから、コンパイルする毎に適当なクラスに設定し直せば、ひとつのObjPtrを色々なクラスのオブジェクトのポインタとして使い回しができるのではないかと思います。しかし、そういう使い方をしてしまうと、そのObjPtrを含むワードやメソッドの実行の度に、各々に適したクラスのオブジェクトを格納しなければならないことになります。長いプログラムは書けないと思います。きっと破綻します。そういうわけで、おとなしい使い方をするのが一番だと思います。つまり、ひとつのクラスのオブジェクトだが中身は初めからはきちんと決まっていないもの、という程度で。こういう事情もあって、Mopsマニュアルでは、PowerMopsについては
Referenceという機構を使うように勧めています。Referenceの方はかなり精巧な造りで、もう少しエラーチェックもあります(完全じゃないですが^^;;)。まあその分少しは重いわけですが。
関連項目:
最終更新:2018年12月24日 16:51