オブジェクトを辞書内にコンパイルしてしまうのではなく、必要になったときにヒープメモリー(プログラムが自由に利用できるメモリ領域)に生成し、必要なくなったときには廃棄する、という使い方をするのが動的オブジェクトです。
他の言語とは違って、Mopsではこのようなオブジェクトの動的生成を、クラスのメソッドとしては実装していません(実装できないことはありませんが)。Mopsでは、そうではなくて、コンテナオブジェクトを利用します。つまり、オブジェクトを格納できる伸縮自在の箱を静的なオブジェクトとして宣言し、その中にオブジェクトを生成する、というわけです。
68kMops以来の標準的なやり方を説明しますが、PowerMopsとiMopsには、
Referenceという機構が導入されました。これは、オブジェクトを格納する変数であると同時に、動的オブジェクトを生成する仕組みも備えており、一個のインスタンスを動的に生成する場合には、そちらを用いる方が便利です。
ここでは、オブジェクトを一つだけ格納できるコンテナである"ObjHandle"を用いて、動的オブジェクトの生成の基本を見てみましょう。
まずObjHandleのインスタンスを静的に生成しておきましょう。
ObjHandle MyDynamicObj
このコンテナの中に、MyClassクラスのインスタンスを生成するワードを書いてみましょう。
: CreateObj ( -- ) [[[']]] MyClass NewObj: MyDynamicObj ; \ NewObj: ( classXT -- )
ClassXTとはクラスのExecution tokenです。インタープリタモードでは「'」を使います(つまり[]で囲わない)。これで、ヒープ上にMopsオブジェクトが生成され、ハンドルがMyDynamicObjのデータ内に登録されます。つまり、ObjHandleはその指定に応じてどんなクラスのオブジェクトでも格納することができるということです。
ところで、Mops既定クラスのいくつかは"NEW:"というメソッドを持っています。他のプログラミング言語では、インスタンスの動的生成を"new"というメソッドでおこなうことが多いので、Mopsクラスの"NEW:"メソッドも、そのためのものだと類推するかもしれません。しかし、そうではありません。この事情は少し複雑です。結論から言えば、"NEW:"メソッドは、Mopsオブジェクトではなくて、それに対応するシステムオブジェクトを生成するためのメソッドです。例えば、ウィンドウやメニューなどGUIオブジェクトは、OSの側にもオブジェクト(多分CarbonではC++オブジェクト)が生成される必要があります。これなしには、ウィンドウなどを出現させることはできません。このオブジェクトはOSにとって必要なデータを保管しているわけですが、Cabon化に伴って細かい内部構造は隠蔽されるようになりました。つまり、オブジェクトに格納されたデータをプログラムが知りたいときには、そのために準備された関数(インターフェイスメソッドと考えてよいと思います)を通さなければならないこととなりました。ですから、システムオブジェクトそのものをMopsオブジェクトとして生成することはできなくなってしまいました(昔はできた)。システムオブジェクトを生成したときには、そのレファレンス(実態はポインタのようです)を返してもらえるので、オブジェクトに関するデータが必要なときは、それを用いて
システムコール関数経由でデータを取ることになります。ですが、システムコールは、Mops全体として見るとあまり効率の良いものではありません(多分、他の言語のプログラムでも)。そこで、何度も必要になるデータは最初に取っておいてMops自身のオブジェクトデータとして格納しておくわけです。Mopsオブジェクトのデータとシステムオブジェクトのデータとは、おそらくほとんど重複するものだと思います。これは、メモリーの利用効率としては少し無駄がある方法ですが、実行効率(速度)の点ではメリットが大きいと思われます。ちなみに、CやC++でのプログラミングのときにも、このようなオブジェクト(構造体)の作り方をすることはあると思います。
関連項目:
最終更新:2018年12月23日 14:01