オブジェクト指向プログラミング

オブジェクトの構造と動作は、クラスの中に記述されている。 それらは、defclassマクロやdefmethod特殊書式により定義されている。 defclassは、クラスの名前・そのスーパークラス・スロット変数名とオプションとして 任意の型およびメッセージの前方への送信を定義する。 defmethodは、メッセージが送られてきたとき呼び出される メソッドを定義する。 クラス定義は、symbolの特殊値として割り当てられる。 クラスは、Common Lispのsutructureのcounter部分と考えることができる。 スロットアクセス関数とsetfメソッドは、defclassによってそれぞれの スロットに自動的に定義される。

大部分のクラスは、内部クラスmetaclassから派生している。 metaclassのサブクラスであるクラスvector-class はベクトルのためのメタクラスである。 もし、class-variablesやclass-methodsを使いたいときは、 metaclassのサブクラスとして自分独自のメタクラスを作り、 メタクラスの名前を:metaclassのキーワードでdefclassに与えればよい。

ベクトルは、その他のrecord-likeオブジェクトと違っている。 なぜなら、ベクトルのインスタンスは、任意の数の要素を持っているが、 record-likeオブジェクトは固定数のスロットを持っている。 EusLispのオブジェクトは、record-likeオブジェクトかまたはベクトルであって、 両方同時ではない。

要素の型が決められているかまたは要素が入れられないベクトルも defclassによって定義することができる。 次の例の中で、クラスintvec5は5つのinteger要素を持つクラス として定義されている。 自動型判定と型変換は、要素がインタープリタによってアクセスされたとき 実施される。 正しい宣言でコンパイルされたとき、高速なアクセスコードが生成される。

(defclass intvec5 :super vector :element-type :integer :size 5)
(setq x (instantiate intvec5))  --> #i(0 0 0 0 0)

メッセージがオブジェクトに送られたとき、 一致するメッセージを最初そのオブジェクトのクラスから探し、次にそのスーパークラスから探して、 スーパークラスが尽きるまで探す。 もし、メソッドが定義されてなかったならば、 前方のリストが探される。 この前方探索は、疑似多重継承によって作られる。 もし、探索が失敗したときは、:nomethodというメソッド名が探され、 メソッドは、全ての引数のリストと一緒に呼び出される。 次の例の中で、メッセージ:telephone:mailperson という型のオブジェクトスロットsecretaryに送られる。 そして、メッセージgo-homeはスロットchauffeurに送られる。

(defclass president :super object
                    :slots ((name :type string)
                            (age  :type :integer)
                            (secretary  :type person
                                        :forward (:telephone :mail))
                            (chauffeur  :forward (:go-home))))

メソッドにおいて、2つのローカル変数(classself) が使用可能となる。 これらの変数は変更すべきでない。 もし、変更したならば、システムから供給された変数は隠され、 send-supersend selfは正しい動作をしない。



Subsections

2016-04-05