7.1. オブジェクトの作成と初期化
ジェネリック関数make-instance
は、 クラスの新しいインスタンスを作成し返却します。 最初の引数はクラスか、クラスの名前であり、 残りの引数は初期化引数リストです。
新しいインスタンスの初期化は、いくつかのステップから成ります。 内容は次のようになります。 指定されなかった初期化引数の値に対して、 明に指定された初期化引数とデフォルト値を結びつけるステップ。 初期化引数の有効性をチェックするステップ。 インスタンスの記憶領域を確保するステップ。 スロットに値を埋めるステップ。 そして追加の初期化を行うためにユーザーが提供したメソッドを実行するステップ。 make-instance
の各ステップはジェネリック関数により実装されているため、 それぞれのステップをカスタマイズする仕組みが提供されています。 加えて、make-instance
自体がジェネリック関数であるため、 自身もカスタマイズできます。
オブジェクトシステムは各ステップに対して、システムで提供されたメソッドを用意しています。 メソッドは初期化全体の手順の標準的な振る舞いを定義したものです。 標準の振る舞いは、下記の4つの簡単な仕組みによって、初期化を制御することができます。
スロットの初期化引数としてのシンボルの宣言。 初期化引数はdefclass
のスロットオプションである、 :initarg
を使うことで宣言できます。 これは、make-instance
の呼び出し時に、 スロットの値を設定するための仕組みとして提供されたものです。
初期化引数のデフォルト値フォームの指定。 初期化引数のデフォルト値フォームは、 defclass
のクラスオプションである:default-initargs
を使うことで定義できます。 もし初期化引数が make-instance
の引数として明に提供されなかった場合、 デフォルト値フォームはdefclass
が宣言されたレキシカル環境の中で評価されます。 そして評価された結果の値は、初期化引数の値として使用されます。
スロットのデフォルト初期化値フォームの提供。スロットのデフォルト初期化値フォームは、 defclass
のスロットオプション:initform
を使うことで宣言されます。 もしmake-instance
の引数かあるいは:default-initargs
のデフォルト値にて、 スロットに対応する初期化引数が与えられていなかった場合、 デフォルト値フォームはdefclass
が宣言されたレキシカル環境の中で評価されます。 そして評価された結果の値はスロットに格納されます。 局所スロットの:initform
フォームは、インスタンスが作成されたとき、 クラスの再定義によりインスタンスを更新するとき、 そしてインスタンスを違うクラスの定義に更新するときに使用されるでしょう。 共有スロットの:initform
フォームに関しては、 定義のときか、再定義のときに使用されます。
initialize-instance
とshared-initialize
のメソッド定義。 スロットの値を設定するこれらの振る舞いは、 システムが提供するメソッドで提供されており、 initialize-instance
は、shared-initialize
を呼び出すように実装されています。 ジェネリック関数shared-initialize
は初期化の部分を実装しており、 次の4つの状況で共有されています。 それは、インスタンス作成時、インスタンスの再初期化時、 クラスの再定義によるインスタンスの更新時、 そして違うクラス定義へインスタンスを更新するときです。 システムが提供するshared-initialize
のメソッドは、 スロットの値を更新するための上記の振る舞いを直接実装しているため、 initialize-instance
は単純にshared-initialize
を呼び出すだけとなります。