% 4.3.6. クラスの再定義
4.3.6. クラスの再定義
standard-class
の直接のインスタンスであるクラスは、
新しいクラスもまたstandard-class
の直接的なインスタンスであるとき、
再定義することができます。
クラスの再定義は、既存のクラスオブジェクトを修正し、
新しいクラス定義へと反映します。
それはクラスに対して新しいクラスオブジェクトを作成するのではありません。
どんなクラスオブジェクトも
以前のdefclass
フォームの
:reader
, :writer
, :accessor
オプションが指定されて生成されたものは、
対応するジェネリック関数から削除されます。
そして、新しいdefclass
フォームのメソッドが追加されます。
再定義されるクラスをC
としたとき、
変更は自身のインスタンスと
そのスーパークラスのどんなインスタンスに対しても伝搬します。
そのようなインスタンスの更新は
実装依存のタイミングで生じますが、
遅くても次回のインスタンスのスロットに対しての
読み込みか書き込み時には行われます。
インスタンスの更新は、
関数eq
によって定義される自身の同一性を変更しません。
更新の処理は特定のインスタンスのスロットを変更するかもしれませんが、
しかしそれは新しいインスタンスを作成するわけではありません。
インスタンスの更新処理によってストレージを消費するかどうかは
実装依存です。
クラスの再定義はスロットの追加か削除が生じるかもしれないことを注意してください。 もしクラスがインスタンスのアクセス可能なローカルスロットの集合を 変更するために再定義されたとき、 そのインスタンスは更新されます。 もしクラスがインスタンスのアクセス可能なローカルスロットの集合を 変更しないような再定義が行われたとき、 インスタンスが更新されるかどうかは実装依存です。
古いクラスと新しいクラスの両方でスロットが共有スロットと指定されていたとき、
その値は保持されます。
もしそのような共有スロットが古いクラスでunbound
のときは、
新しいクラスでもunbound
です。
古いクラスでローカルだったスロットが
新しいクラスで共有スロットに指定されたときは初期化されます。
新しく追加された共有スロットは初期化されます。
新しく追加されたそれぞれの共有スロットは、
新しいクラスのdefclass
フォームで指定されたスロットの
捕捉された初期化フォームが評価された結果にセットされます。
もし初期化フォームが無かったときは、そのスロットはunbound
です。
もしクラスの再定義が
そのクラスのインスタンスの
アクセス可能なローカルスロットの集合を
変更するように再定義されたとき、
そのクラスのインスタンスの変更は、
二段階の更新処理を行います。
その処理は、ジェネリック関数のmake-instances-obsolete
を
起動することによって明示的に開始するかもしれません。
その二段階の処理はいくつかの実装では違う状況で実行することができます。
例えば、ある実装ではその二段階の処理は
ストレージ内のスロットの順番が変更されたときに開始されます。
最初のステップは、そのインスタンスの構造を新しいクラスの定義から 新しいローカルスロットの追加かローカルスロットの削除による修正を行います。 次のステップは、新しく追加されたローカルスロットの初期化を行い、 その他のユーザー定義の動作を実行します。 二段階のステップは、次に示される二つの章によって定義されます。