% Standard-Generic-Function UPDATE-INSTANCE-FOR-REDEFINED-CLASS
Standard Generic Function UPDATE-INSTANCE-FOR-REDEFINED-CLASS
update-instance-for-redefined-class
instance add-slots discarded-slots property-list
&rest initargs &key &allow-other-keys => result*
update-instance-for-redefined-class
(instance standard-object
)
added-slots discarded-slots property-list &rest initargs
instance - オブジェクト
added-slots - リスト
discarded-slots - リスト
property-list - リスト
initargs - 初期化引数リスト
result - オブジェクト
ジェネリック関数update-instance-for-redefined-class
は、
プログラマーによって呼び出されることを意図していません。
プログラマーはこの関数のメソッドを作成できます。
関数update-instance-for-redefined-class
は、
関数make-instances-obsolete
によって
有効化される仕組みによって呼び出されます。
システムが提供するupdate-instance-for-redefined-class
の
プライマリメソッドは、initargsの有効性を確認し、
もしinitargsに有効として宣言されていないものが与えられていた場合は
エラーが通知されます。
このメソッドは、initargsに対応する値でスロットを初期化します。
そして新たに追加されたスロットadded-slotsには
:initform
フォーム対応した値で初期化します。
このような動作は、ジェネリック関数shared-initialize
を
次のような引数で呼び出すことで行います。
引数は、instance、
instanceに新しく追加されたスロットの名前のリストadded-slots、
そして受け取ったinitargsです。
新しく追加されたスロットadded-slotsとは、
以前のクラスに同じ名前のスロットが存在しない局所スロットのことです。
make-instances-obsolete
が起動されるときか、
クラスが再定義されてinstanceが更新されるときは、
元のインスタンスの全ての削除されるスロットdiscarded-slotsとその値が、
スロットの名前と値とともに取り出されproperty-listが作成されます。
instanceの構造は、現在のクラスの定義に合うように変換されます。
update-instance-for-redefined-class
の引数は、
変換されたinstance、
インスタンスへ追加されたスロットのリストadded-slots、
インスタンスから削除されるスロットのリストdiscarded-slots、
削除されるスロットで値を持っているの
スロットの名前と値が含まれるリストproperty-listです。
削除されるスロットのリストは、古いクラスでは局所スロットだったものから、
新しいクラスでは共有スロットになったものが含まれます。
(defclass position () ())
(defclass x-y-position (position)
((x :initform 0 :accessor position-x)
(y :initform 0 :accessor position-y)))
;;; 極座標は直交座標よりも多く使用されることが判明したため、
;;; 表現を変更し、いくつかの新しいaccessorメソッドを追加しました。
(defmethod update-instance-for-redefined-class :before
((pos x-y-position) added deleted plist &key)
;; x-y座標を極座標に変換し新しいスロットに保存します
(let ((x (getf plist 'x))
(y (getf plist 'y)))
(setf (position-rho pos) (sqrt (+ (* x x) (* y y)))
(position-theta pos) (atan y x))))
(defclass x-y-position (position)
((rho :initform 0 :accessor position-rho)
(theta :initform 0 :accessor position-theta)))
;;; 全ての古いx-y-positionインスタンスは、
;;; 自動的にアップデートされるでしょう。
;;; 新しい表現は、旧来の表現と同じような見た目が与えられています。
(defmethod position-x ((pos x-y-position))
(with-slots (rho theta) pos (* rho (cos theta))))
(defmethod (setf position-x) (new-x (pos x-y-position))
(with-slots (rho theta) pos
(let ((y (position-y pos)))
(setq rho (sqrt (+ (* new-x new-x) (* y y)))
theta (atan y new-x))
new-x)))
(defmethod position-y ((pos x-y-position))
(with-slots (rho theta) pos (* rho (sin theta))))
(defmethod (setf position-y) (new-y (pos x-y-position))
(with-slots (rho theta) pos
(let ((x (position-x pos)))
(setq rho (sqrt (+ (* x x) (* new-y new-y)))
theta (atan new-y x))
new-y)))
なし。
システムが提供するupdate-instance-for-redefined-class
の
プライマリメソッドは、
initargsに有効として宣言されていないものが与えられていた場合は
エラーが通知されます。
make-instances-obsolete
,
shared-initialize
,
4.3.6. クラスの再定義,
7.1.4. 初期化引数の規則,
7.1.2. 初期化引数の有効性の宣言
initargsは、defclass
の:initarg
引数によって、
あるいはupdate-instance-for-redefined-class
か
shared-initialize
のメソッドの宣言によって、
有効であると宣言されます。
update-instance-for-redefined-class
か
shared-initialize
の各メソッドの宣言のラムダリストにある、
各キーワードパラメーター指定子のキーワード名は、
それらのメソッドが適用されるすべてのクラスに対して、
有効な初期化引数の名前として宣言されます。