User Tools


Standard Generic Function CHANGE-CLASS

Syntax

  • change-class instance new-class &key &allow-other-keysinstance

Method Signatures

Arguments and Values

Description

The generic function change-class changes the class of an instance to new-class. It destructively modifies and returns the instance.

If in the old class there is any slot of the same name as a local slot in the new-class, the value of that slot is retained. This means that if the slot has a value, the value returned by slot-value after change-class is invoked is eql to the value returned by slot-value before change-class is invoked. Similarly, if the slot was unbound, it remains unbound. The other slots are initialized as described in \secref\ChangingInstanceClass.

After completing all other actions, change-class invokes update-instance-for-different-class. The generic function update-instance-for-different-class can be used to assign values to slots in the transformed instance. See section {\secref\InitNewLocalSlots}.

If the second of the above methods is selected, that method invokes change-class on instance, (find-class new-class), and the initargs.

Examples

(defclass coords () ())

#<STANDARD-CLASS COMMON-LISP-USER::COORDS>

(defclass x-y-coords (coords) ((x :initform 0 :initarg :x) (y :initform 0 :initarg :y)))

#<STANDARD-CLASS COMMON-LISP-USER::X-Y-COORDS>

(defclass rho-theta-coords (coords) ((rho :initform 0) (theta :initform 0)))

#<STANDARD-CLASS COMMON-LISP-USER::RHO-THETA-COORDS>

Below, we copy the coords information from old to new to make new be a rho-theta-coords at the same coords as old.

(defmethod update-instance-for-different-class :before ((old x-y-coords) (new rho-theta-coords) &key) (let ((x (slot-value old 'x)) (y (slot-value old 'y))) (setf (slot-value new 'rho) (sqrt (+ (* x x) (* y y))) (slot-value new 'theta) (atan y x))))

#<STANDARD-METHOD COMMON-LISP:UPDATE-INSTANCE-FOR-DIFFERENT-CLASS :BEFORE (X-Y-COORDS RHO-THETA-COORDS) {100274300F}>

At this point an instance of the class x-y-coords can be changed to be an instance of the class rho-theta-coords using change-class:

(defparameter *coords-1* (make-instance 'x-y-coords :x 2 :y 0))

*COORDS-1*

*coords-1*

#<X-Y-POSITION {1002984B53}>

(change-class *coords-1* 'rho-theta-coords)

#<RHO-THETA-POSITION {1002984B53}>

The result is that the instance bound to *coords-1* is now an instance of the class rho-theta-coords. The update-instance-for-different-class method performed the initialization of the rho and theta slots based on the value of the x and y slots, which were maintained by the old instance.

Examples

None.

Affected By

None.

Exceptional Situations

None.

See Also

Notes

The generic function change-class has several semantic difficulties. First, it performs a destructive operation that can be invoked within a method on an instance that was used to select that method. When multiple methods are involved because methods are being combined, the methods currently executing or about to be executed may no longer be applicable. Second, some implementations might use compiler optimizations of slot access, and when the class of an instance is changed the assumptions the compiler made might be violated. This implies that a programmer must not use change-class inside a method if any methods for that generic function access any slots, or the results are undefined.

\issue{CHANGE-CLASS-INITARGS:PERMIT} \issue{CHANGE-CLASS-INITARGS:PERMIT} \issue{CHANGE-CLASS-INITARGS:PERMIT} \issue{CHANGE-CLASS-INITARGS:PERMIT} \issue{CHANGE-CLASS-INITARGS:PERMIT}