% Macro DEFCLASS
Macro DEFCLASS
defclass
class-name (superclass-name*) (slot-specifier*) [[class-option]]
=> new-class
slot-specifier ::= slot-name | (slot-name [[slot-option]])
slot-name ::= symbol
slot-option ::= {:reader reader-function-name}* |
{:writer writer-function-name}* |
{:accessor reader-function-name}* |
{:initarg initarg-name}* |
{:initform form} |
{:type type-specifier} |
{:documentation string}
function-name ::= {symbol | (setf symbol)}
class-option ::= (:default-initargs . initarg-list) |
(:documentation string) |
(:metaclass class-name)
class-name - nil
ではないシンボル
superclass-name - nil
ではないシンボル
slot-name - シンボル。
引数slot-nameは、変数名として使用できる構文として有効なシンボルです。
reader-function-name - nil
ではないシンボル。
:reader
はひとつのスロットに複数指定できます。
writer-function-name - ジェネリック関数名。
:reader
はひとつのスロットに複数指定できます。
accessor-function-name - nil
ではないシンボル。
:accessor
はひとつのスロットに複数指定できます。
allocation-type - (member :instance :class)
。
ひとつのスロットに最大ひとつの指定ができます。
initarg-name - シンボル。
:initarg
はひとつのスロットに対して複数指定できます。
form - フォーム。
:initform
はひとつのスロットに最大ひとつの指定ができます。
type-specifier - 型指定子。
:type
はひとつのスロットに最大ひとつの指定ができます。
class-option - クラス全体か、全てのクラスのスロットを示します。
initarg-list - 名前とデフォルトの初期化値のフォームを
交互に並べた初期化引数のリストです。
:default-initargs
は最大ひとつの指定ができます。
class-name - nil
ではないシンボル。:metaclass
は最大ひとつの指定ができます。
new-class - 新しいクラスのオブジェクト
マクロdefclass
は、新しい名前の付いたクラスを定義します。
その結果として新しいクラスオブジェクトが返却されます。
defclass
の構文は、
スロットの初期化引数を指定するオプション、
スロットのデフォルト初期化値を指定するオプション、
そしてスロットの値を読み書きするためのジェネリック関数のメソッドを
自動的に生成するようなオプションを提供します。
デフォルトではリーダおよびライタ関数は定義されていませんので、
その生成は明示的に要求する必要があります。
ただし、スロットは常にslot-value
を使用してアクセスすることができます。
新しいクラスを定義すると、同じ名前の型も定義されます。
式(typep object class-name)
は、
引数objectのクラスがclass-name自身の名前のクラスであるか、
あるいはクラスclass-nameのサブクラスであるならば、trueを返します。
クラスオブジェクトは型指定子として使われることができます。
したがって(typep object class)
は、
objectのクラスが、クラス自体か、
クラスのサブクラスである場合にtrueを返します。
引数のclass-nameは、新しいクラスの適切な名前を指定します。
もし同名のクラスが存在しており、
そのクラスがstandard-class
のインスタンスであり、
さらにdefclass
フォームによる新しいクラスの定義が、
standard-class
クラスのクラスで指定されていた場合、
既存のクラスは再定義され、
そのクラス(サブクラスも含む)のインスタンスは、
それらが次にアクセスされたときに
新しい定義へと更新されます。
詳細は4.3.6. クラスの再定義を参照。
引数superclass-nameは、新しいクラスのダイレクトスーパークラスを指定します。
もしスーパークラスのリストが空のとき、
スーパークラスはメタクラスによって異なるデフォルト値になりますが、
standard-class
のデフォルトはstandard-object
です。
新しいクラスは、各ダイレクトスーパークラスと、 それら各々のダイレクトスーパークラスの繋がりによって、 スロットとメソッドが継承されます。
スロットオプションは下記のものが使用可能です。
:reader
は、
スロットの値を読み込むための
reader-function-nameという名前のジェネリック関数と、
修飾子がないメソッドをを定義します。:writer
は、
スロットの値を書き込むための
writer-function-nameという名前のジェネリック関数と、
修飾子がないメソッドをを定義します。:accessor
は、
スロットの値を読み込むための
accessor-function-nameという名前のジェネリック関数と、
修飾子がないメソッドをを定義します。
さらに、スロットの値をsetf
を用いて修正するための
(setf accessor-function-name)
という名前のジェネリック関数と、
修飾子がないメソッドをを定義します。:allocation
は、
割り当てられたスロットが、どこのストレージを使用するかを指定します。
スロットのストレージは、各インスタンスか、
クラスオブジェクト自身に配置することができます。
引数allocation-type
の値は、
:instance
キーワードか、:class
キーワードのどちらかです。
もし:allocation
スロットオプションが指定されなかったときは、
:allocation :instance
が指定されたと同じ効果になります。
:instance
のとき、
名前がslot-nameの局所スロットは、
クラスのそれぞれのインスタンスに配置されます。:class
のとき、指定された名前の共有スロットは、
defclass
フォームによって生成されたクラスオブジェクトに配置されます。
このスロットの値は、そのクラスの全てのインスタンスによって共有されます。
もしクラスC1
に共有スロットがあるとき、
C1
のサブクラスC2
はこのひとつのスロットが共有されるでしょう。
ただしC2
のdefclass
フォームで同名のスロットが
指定された場合は共有されません。
さらに、C2
のクラス優先順位リストを見て、
C2
のスーパークラスのうちのC1
より先行しているものがあり、
そのクラスが同名のスロットを定義していた場合でも、
スロットの共有は行われません。:initform
は、デフォルト初期値のフォームであり、
スロットの初期値として使用されます。
このフォームは、スロットを初期化するときに毎回評価されます。
このフォームが評価されるときのレキシカルな環境は、
defclass
フォームが評価されたときのものになります。
レキシカルな環境は、変数と関数両方を参照することに注意してください。
局所スロットでは、動的な環境は
make-instance
が呼ばれた場所であり、
共有スロットでは、defclass
が評価された場所です。
詳細は7.1. オブジェクトの作成と初期化をご確認ください。
defclass
の構文を(slot-name :initform form)
から
省略して(slot-name form)
にすることは許されません。:initarg
は、
初期化引数の名前をinitarg-nameで宣言し、
そのスロットが初期化引数で初期化されるように指定します。
もしinitialize-instance
呼び出し時に
初期化引数が値を持っているときは、
そのスロットに値が格納され、
そのスロットに:initform
オプションがある場合は評価されません。
初期化引数にスロットの値がないときは、
そのスロットは、:initform
オプションが指定されてるとき、
その内容に従って初期化されます。:type
は、
スロットの内容が常に指定された型であることを指定します。
これは、このクラスのオブジェクトが適用できるリーダーのジェネリック関数の
返却値の型を宣言する効果があります。
そのスロットの型に違反した値を保存しようとしたときの結果は未定義です。
スロットオプション:type
は、7.5.3. スロットの継承とスロットオプションで詳しく説明しています。:documentation
は、
スロットに、ドキュメント文字を提供します。
:documentation
はひとつのスロットに、最大ひとつ指定できます。各クラスオプションは、クラス全体の設定です。
クラスオプションは下記のものが使用可能です。
:default-initargs
は、
名前とデフォルトの初期化値のフォームを交互に並べた
初期化引数のリストによって続けられます。
もし、これらの初期化引数のどれかが、
make-instance
に与えられた初期化引数リストに現れない場合、
対応するデフォルト初期値フォームが評価され、
その初期化引数名とフォームの値が
初期化引数リストの最後に追加されてからインスタンスが生成されます。
詳しくは7.1. オブジェクトの作成と初期化をご確認ください。
デフォルト初期値フォームは、使用されるたびに評価されます。
評価されるときのレキシカルな環境は、
defclass
フォームが評価されたときのものです。
動的な環境は、make-instance
が呼ばれたときのものです。
もしクラスオプション:default-initargs
に
初期化引数名が複数現れたときは、
エラーが発生します。:documentation
は、
クラスオブジェクトにドキュメント文字を、
種別type
で、class-nameに割り当てます。
:documentation
は、最大ひとつ指定できます。:metaclass
は、
定義するクラスのインスタンスが、
システムが提供するデフォルトのもの(standard-class
のクラス)とは
異なるメタクラスを持つことを指定するために使われます。標準クラスにおいては、defclass
は下記のルールに注意してください。
defclass
フォームによってクラスが評価される前に、
そのクラスのスーパークラスが定義されている必要はありません。defmethod
フォームで
特定パラメーターとして使用される前には、
そのクラスは定義されていなければなりません。オブジェクトシステムは、これらのルールに従わない場合にも 対応できるように拡張することが可能です。
いくつかのスロットは、
スーパークラスのクラスによって継承され、いくつかのものは隠蔽され、
あるいは局所スロットの定義によって変更されます。
クラスオプションは、:default-initargs
以外継承されません。
スロットとスロットオプションがどのように継承されるかの詳しい説明は、
7.5.3. スロットの継承とスロットオプションをご確認ください。
defclass
のオプションは拡張できます。
すべての実装は、自身が実装していない
クラスオプションやスロットオプションを見た場合は、
エラーを通知することが要求されています。
複数のreader, writer, accessorを指定したり、 あるスロットに複数の初期化引数を指定するのは正しいです。 その他のスロットオプションが ひとつのスロットの定義に複数指定することはできませんので、 エラーが発生します。
もし、あるスロットにreader, writer, accessorが指定されていないとき、
そのスロットはただslot-value
によってのみアクセスできます。
もしdefclass
フォームがトップレベルに現れたとき、
コンパイラーはクラス名を有効な型の名前であると認識し、
後続の宣言(たとえばdeftype
)や、
defmethod
の特定パラメーター、
またdefclass
の:metaclass
オプションでも使用できるようにしなければならない。
コンパイラーは、find-class
の環境の引数に、
マクロの環境パラメーターで受け取った値を指定したときは、
クラスの定義を返却できるようにしなければならない。
なし。
なし。
もしスロットの名前に重複があった場合は、
型program-error
のエラーが発生します。
もし、クラスオプション:default-initargs
に
初期化引数の名前が複数現れたときは、
型program-error
のエラーが発生します。
もし、スロットオプション
:allocation
, :initform
, :type
, :documentation
が
ひとつのスロットの定義に複数現れたときは、
型program-error
のエラーが発生します。
すべての実装は、自身が実装していない
クラスオプションやスロットオプションを見た場合は、
型program-error
のエラーが通知することを要求されています。
documentation
,
initialize-instance
,
make-instance
,
slot-value
,
4.3. クラス,
4.3.4. 継承,
4.3.6. クラスの再定義,
4.3.5. クラス優先順位リストの決定,
7.1. オブジェクトの作成と初期化
なし。