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. オブジェクトの作成と初期化
なし。