For Development HEAD DRAFTSearch (procedure/syntax/module):

2.5 統合されたオブジェクトシステム

GaucheはCLOSに類似した、STklosスタイルのオブジェクトシステムを持っています。 あなたが何らかのオブジェクト指向(OO)言語を使ったことがあれば、 基本的な使い方は簡単にわかるでしょう。

;; x, y座標を持つpointクラスを定義
(define-class point ()
  ((x :init-value 0)
   (y :init-value 0))
  )

(define-method move ((p point) dx dy)
  (inc! (slot-ref p 'x) dx)
  (inc! (slot-ref p 'y) dy))

(define-method write-object ((p point) port)
  (format port "[point ~a ~a]"
          (slot-ref p 'x)
          (slot-ref p 'y)))

しかし、主流のオブジェクト指向言語に慣れてはいるがCLOSスタイルのオブジェクトシステムに 慣れていないプログラマは、Gaucheのオブジェクトシステムの詳細を見てゆくと 奇妙に感じることがあるのではないかと思います。 ここではGaucheのオブジェクトシステムの代表的な性質を簡単に述べておきます。 詳しくはオブジェクトシステムの章を参照して下さい。

全てはオブジェクトである (それが気になる人には)

このような主張は他のOO言語でも見たことがあるでしょう。 Gaucheもその例にもれず、実行時にクラスを得たりメソッドを呼び出したりといった 操作が任意のオブジェクトに対して出来るという意味で、全てはオブジェクトです。 また組込みクラスを含めたどんなクラスに対しても新しいメソッドを定義することができます。

しかし、CLOS系のパラダイムでは、全てがオブジェクトかどうかという議論はあまり 問題ではありません。というのは次のような性質があるからです。

メソッドは全ての引数によってディスパッチされる

C++、Objective C、Python、RubyなどのOO言語では、メソッドは特定のクラスに 所属しています。Gaucheではメソッドはクラスに従属しません。

例えば、数値だけを要素に持つベクタークラス<num-vector>と 行列クラス<num-matrix>を定義したとします。 プログラマは、以下のようなあらゆる場合についてメソッドproductを 別々に定義することができます。

  (product <num-vector> <num-matrix>)
  (product <num-matrix> <num-vector>)
  (product <num-vector> <num-vector>)
  (product <num-matrix> <num-matrix>)
  (product <number>     <num-vector>)
  (product <number>     <num-matrix>)
  (product <number>     <number>)

これらの各メソッドは、<num-vector>クラスや<num-matrix> クラスに所属するわけではありません。

メソッドがクラスに所有されているわけではないので、既に存在するクラスに対していつでも 独自のメソッドを定義することができます(但し、いくつかの組込みクラスの既定のメソッドには 変更できないものがあります)。上の例で既にこれは示されています。プログラマは メソッドproductを組込みクラス<number>に対して定義することが できます。これが、全てはオブジェクトであるかどうかはCLOSスタイルのオブジェクトシステム では問題にならないと言った理由です。

少し詳しいことを言えば、メソッドはジェネリック関数に属しており、 ジェネリック関数が適切なメソッドを選ぶ役割を果たします。

クラスはインスタンスでもある

デフォルトでは、クラスは<class>というクラスのインスタンスであり、 ジェネリック関数は<generic>というクラスのインスタンスです。 しかし、<class>を継承したクラスを定義することにより、 オブジェクトの初期化がどのように行われるかとか、スロットがどのように アクセスされるかといった動作をカスタマイズすることができます。 また、<generic>を継承したクラスを定義することにより、 適用可能なメソッドがどのように選択されて、どのような順序で適用されるか といったことがカスタマイズ可能です。このメカニズムはメタオブジェクトプロトコル と呼ばれています。メタオブジェクトプロトコルは、言語をその言語そのもので拡張する方法と 言えるでしょう。

例として、ディストリビューションに含まれるlib/gauche/mop/singleton.scmlib/gauche/mop/validator等があります。src/libobj.scmを 読めば、クラス自身がGaucheでどのように定義されているかがわかります。 メタオブジェクトプロトコルの更に詳しいことについては、次の書籍が参考になります: Gregor Kiczales, Jim Des Rivieres, Daniel Bobrow, The Art of Metaobject Protocol, The MIT Press.

クラスは名前空間を作らない

メインストリームのOO言語ではクラスが名前空間を作ることがよくあります。 CLOSスタイルのオブジェクトシステムはそうではありません。 Gaucheでは、名前空間はオブジェクトシステムとは直交する、 モジュールシステムによって管理されます。



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT