[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
CLOS 風のオブジェクトシステムでは、オブジェクトシステムがそれ自身の上に
構築されます。すなわち、クラス構造のようなもの、クラスをどのように
生成するか、インスタンスをどのように生成し初期化するか、メソッドをどのように
ディスパッチし呼び出すか、これらはすべてオブジェクトシステムによって、
定義されます。たとえば、クラスはジェネリックな構造と標準的クラスの
振舞いを定義する <class>
クラスのインスタンスです。<class>
をサブクラス化すると、デフォルトのものとは違う振舞いをする、独自の
クラス集合をつくることができます。これは結局、独自のオブジェクトシステムを
つくることになります。
メタオブジェクトプロトコルは、どのようにオブジェクトシステムを 構築するかに関連する API 群の定義です。ブロック構築のクラス、オブジェクト システムを操作するあいだに呼ばれるジェネリック関数の名前と順序などです。 これらのクラスをサブクラス化し、これらのメソッドを特定化することは、 オブジェクトシステムの振舞いをカスタマイズすることを意味します。
7.6.1 クラスのインスタンシエーション | ||
7.6.2 スロットアクセスのカスタマイズ | ||
7.6.3 メソッドのインスタンシエーション | ||
7.6.4 メソッド適用のカスタマイズ |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
すべてのクラスはある特殊なクラスのグループのインスタンスになっています。
他のクラスのクラスになれるようなクラスのことを メタクラス と呼びます。
Gauche では <class>
クラスおよびそのサブクラスのみがメタクラスに
なれます。
define-class
の展開 define-class
マクロは基本的には <class>
(あるいは指定された
メタクラス)のインスタンスを生成するコードのラッパーで、それを与えられた
名前に束縛します。以下のような define-class
形式を前提とします。
(define-class name (supers) slot-specs options …) |
これを次のように展開します。
(‘`gauche-config --syslibdir`/gauche/object.scm’ の define-class
マクロの定義をみれば展開形式を見ることができます。)
(define name (let ((tmp1 (make metaclass :name 'name :supers (list supers) :slots (map process-slot-definitions slot-specs) :defined-modules (list (current-module)) options …))) … check class redefinition … … registering accessor methods … tmp1)) |
生成されるクラスのクラス、つまり、metaclass は以下のルールで 決定されます。
:metaclass
オプションが define-class
マクロに
与えられていれば、その値を使います。その値は、<class>
クラスか
あるいはその子孫でなければなりません。
<class>
であるなら、生成される
クラスのメタクラスも <class>
になります。
<class>
かあるいは別のメタクラス
A
のどちらかであれば、生成されるクラスのメタクラスは、A
に
なります。
<class>
以外の 2つ以上のメタクラス
(A
, B
, C
…)を含む場合、生成されるクラスの
メタクラスはこれらのメタクラス A
, B
, C
… すべてを
継承したメタクラスになります。
クラスの名前、スーパークラス、スロットの定義は初期化引数として
ジェネリック関数 make
に引き渡され、それ以外の引数は
define-class
に引き渡されます。初期化引数 define-modules
は
どのモジュールでそのクラスが定義されたかを覚えておくために引き渡されます。
これはこのクラスの再定義のとき用です。
スロットの仕様 slot-specs は内部メソッド process-slot-definitions
(これは直接呼び出すことはできません)で処理され、スロット定義になります。
厳密には、:init-form
スロットオプションは、:init-thunk
オプション
になり、:getter
、:setter
、:accessor
のスロットオプションは
引用されます。
クラス(metaclass のインスタンス)が生成された後、name のグローバル な束縛がチェックされます。それが、クラスに束縛されていれば、クラスの再定義 プロトコルが起動されます(クラスの再定義 参照)。
その後、slot-specs 中で、:getter
、:setter
、
:accessor
スロットオプションに与えられたメソッドが集められ、対応する
ジェネリック関数に登録されます。
すべてのメタクラスのベースクラスである <class>
は以下のような
スロットを持っています。これらのスロットは内部的な管理のためにあるので
クラスが初期化された後に、これらの値を変更すべきではないということに
注意してください。クラスの情報を得るには、これらのスロットに直接
アクセスするのではなく、クラスオブジェクト にある手続きを使うことをおすすめ
します。
クラスの名前、define-class
マクロに与えられたシンボルです。
class-name
はこの値を返します。
クラス順位リストです。class-precedence-list
はこの値を返します。
直接スーパークラスのリストです。
class-direct-supers
はこの値を返します。
スロットアクセサの連想リストです。これは各スロットがどのようにアクセスされる べきかをカプセル化しています。
スロット定義のリストです。class-slots
はこの値を返します。
スロット定義についての詳細は、スロット定義オブジェクト を参照してください。
このクラスの定義で直接指定された(つまり継承したものではない)スロット定義の
リストです。class-direct-slots
はこの値を返します。
インスタンスにアロケートされるスロットの数です。
このクラスを直接継承しているクラスのリストです。
class-direct-subclasses
はこの値を返します。
このクラスを特定化子リスト中にもつメソッドのリストです。
class-direct-methods
はこの値を返します。
このクラスが生成されるときの初期化引数リストです。この情報は 再定義されたクラスを初期化するのに使います(クラスの再定義 参照)。
このクラスがグローバル束縛をもつモジュールのリストです。
このクラスが再定義された場合、このスロットは新しいクラスへの参照を含みます。
そうでない場合にはこのスロットは #f
をもっています。
このスロットの値は、このクラスがどのように生成されたかを示しています。
Scheme 定義のクラスは、scheme
というシンボルを持っています。それ以外の
値は内部的に使用するだけです。
<class>
用の make メソッド [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.