User Tools

A PCRE internal error occured. This might be caused by a faulty plugin

====== 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}