User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:functions:change-class [2019/07/14 17:00]
cl:functions:change-class [2019/07/18 14:00] (current)
Line 1: Line 1:
 +====== Standard Generic Function CHANGE-CLASS ======
 +
 +====Syntax====
 +  * **change-class** //instance new-class ''&​key''​ ''&​allow-other-keys''//​ → //​instance//​
 +
 +====Method Signatures====
 +  * **change-class** (//​instance//​ **[[CL:​Types:​standard-object]]**) (//​new-class//​ **[[CL:​Types:​standard-class]]**) //''&​rest''​ initargs//
 +  * **change-class** (//​instance//​ **[[CL:​Types:​t]]**) (//​new-class//​ **[[CL:​Types:​symbol]]**) //''&​rest''​ initargs//
 +  ​
 +====Arguments and Values====
 +  * //​instance//​ - an //​[[CL:​Glossary:​object]]//​.
 +  * //​new-class//​ - a //​[[CL:​Glossary:​class designator]]//​.
 +  * //​initargs//​ - an //​[[CL:​Glossary:​initialization argument list]]//.
 +
 +====Description====
 +The //​[[CL:​Glossary:​generic function]]//​ **change-class** changes the //​[[CL:​Glossary:​class]]//​ of an //​instance//​ to //​new-class//​. It destructively modifies and returns the //​instance//​.
 +
 +If in the old //​[[CL:​Glossary:​class]]//​ there is any //​[[CL:​Glossary:​slot]]//​ of the same name as a local //​[[CL:​Glossary:​slot]]//​ in the //​new-class//,​ the value of that //​[[CL:​Glossary:​slot]]//​ is retained. This means that if the //​[[CL:​Glossary:​slot]]//​ has a value, the value returned by **[[CL:​Functions:​slot-value]]** after **change-class** is invoked is **[[CL:​Functions:​eql]]** to the value returned by **[[CL:​Functions:​slot-value]]** before **change-class** is invoked. Similarly, if the //​[[CL:​Glossary:​slot]]//​ was unbound, it remains unbound. The other //​[[CL:​Glossary:​slot|slots]]//​ are initialized as described in \secref\ChangingInstanceClass.
 +
 +After completing all other actions, **change-class** invokes **[[CL:​Functions:​update-instance-for-different-class]]**. The generic function **[[CL:​Functions:​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 //​[[CL:​Glossary:​method|methods]]//​ is selected, that //​[[CL:​Glossary:​method]]//​ invokes **change-class** on //​instance//,​ ''​(find-class //​new-class//​)'',​ and the //​initargs//​.
 +
 +====Examples====
 +<​blockquote>​
 +([[CL:​Macros:​defclass]] coords () ())
 +<​r>#<​STANDARD-CLASS COMMON-LISP-USER::​COORDS></​r>​
 +
 +([[CL:​Macros:​defclass]] x-y-coords (coords) ​
 +  ((x :initform 0 :initarg :x) 
 +   (y :initform 0 :initarg :y)))
 +<​r>#<​STANDARD-CLASS COMMON-LISP-USER::​X-Y-COORDS></​r>​
 +
 +([[CL:​Macros:​defclass]] rho-theta-coords (coords) ​
 +  ((rho :initform 0) 
 +   ​(theta :initform 0)))
 +<​r>#<​STANDARD-CLASS COMMON-LISP-USER::​RHO-THETA-COORDS></​r>​
 +</​blockquote>​
 +
 +Below, we copy the coords information from //old// to //new// to make //new// be a ''​rho-theta-coords''​ at the same coords as //​old//​. ​
 +
 +<​blockquote>​
 +([[CL:​Macros:​defmethod]] update-instance-for-different-class :​before ​
 +    ((old x-y-coords) (new rho-theta-coords) &​key) ​
 +  ([[CL:​Special Operators:​let]] ((x ([[CL:​Functions:​slot-value]] old '​x)) ​
 +        (y ([[CL:​Functions:​slot-value]] old 'y)))
 +    ([[CL:​Macros:​setf]] ([[CL:​Functions:​slot-value]] new 'rho) ([[CL:​Functions:​sqrt]] ([[CL:​Functions:​math-add|+]] ([[CL:​Functions:​math-multiply|*]] x x) ([[CL:​Functions:​math-multiply|*]] y y))) 
 +          ([[CL:​Functions:​slot-value]] new '​theta) ([[CL:​Functions:​atan]] y x))))
 +<​r>#<​STANDARD-METHOD COMMON-LISP:​UPDATE-INSTANCE-FOR-DIFFERENT-CLASS ​
 +                     :​BEFORE (X-Y-COORDS RHO-THETA-COORDS) {100274300F}></​r>​
 +</​blockquote>​
 +
 +At this point an //​[[CL:​Glossary:​instance]]//​ of the //​[[CL:​Glossary:​class]]//​ ''​x-y-coords''​ can be changed to be an //​[[CL:​Glossary:​instance]]//​ of the //​[[CL:​Glossary:​class]]//​ ''​rho-theta-coords''​ using **change-class**:​
 +
 +<​blockquote>​
 +([[CL:​Macros:​defparameter]] *coords-1* ([[CL:​Functions:​make-instance]] '​x-y-coords :x 2 :y 0)) <​r>​*COORDS-1*</​r>​
 +*coords-1* <​r>#<​X-Y-POSITION {1002984B53}></​r>​
 +(change-class *coords-1* '​rho-theta-coords) <​r>#<​RHO-THETA-POSITION {1002984B53}></​r>​
 +</​blockquote>​
 +
 +The result is that the //​[[CL:​Glossary:​instance]]//​ //​[[CL:​Glossary:​bound]]//​ to ''​*coords-1*''​ is now an //​[[CL:​Glossary:​instance]]//​ of the //​[[CL:​Glossary:​class]]//​ ''​rho-theta-coords''​. The **[[CL:​Functions:​update-instance-for-different-class]]** //​[[CL:​Glossary:​method]]//​ performed the //​[[CL:​Glossary:​initialization]]//​ of the ''​rho''​ and ''​theta''​ slots based on the value of the ''​x''​ and ''​y''​ //​[[CL:​Glossary:​slot|slots]]//,​ which were maintained by the old //​[[CL:​Glossary:​instance]]//​.
 +
 +====Examples====
 +None.
 +
 +====Affected By====
 +None.
 +
 +====Exceptional Situations====
 +None.
 +
 +====See Also====
 +  * **[[CL:​Functions:​update-instance-for-different-class|Generic Function UPDATE-INSTANCE-FOR-DIFFERENT-CLASS]]**
 +  * {\secref\ChangingInstanceClass}
 +
 +====Notes====
 +The generic function **change-class** has several semantic difficulties. First, it performs a destructive operation that can be invoked within a //​[[CL:​Glossary:​method]]//​ on an //​[[CL:​Glossary:​instance]]//​ that was used to select that //​[[CL:​Glossary:​method]]//​. When multiple //​[[CL:​Glossary:​method|methods]]//​ are involved because //​[[CL:​Glossary:​method|methods]]//​ are being combined, the //​[[CL:​Glossary:​method|methods]]//​ currently executing or about to be executed may no longer be applicable. Second, some implementations might use compiler optimizations of slot //​[[CL:​Glossary:​access]]//,​ and when the //​[[CL:​Glossary:​class]]//​ of an //​[[CL:​Glossary:​instance]]//​ is changed the assumptions the compiler made might be violated. This implies that a programmer must not use **change-class** inside a //​[[CL:​Glossary:​method]]//​ if any //​[[CL:​Glossary:​method|methods]]//​ for that //​[[CL:​Glossary:​generic function]]//​ //​[[CL:​Glossary:​access]]//​ any //​[[CL:​Glossary:​slot|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}