Jean-Claude Beaudoin jean.claude.beaudoin@gmail.com wrote:
My main stance here is to state that I have yet to see, in a significant application, any use of functions #'cl:make-instance-obsolete and #'cl:update-instance-for-redefined-class and of the underlying machinery that support the remorphing of instances following a class redefinition (through a subsequent cl:defclass most likely). I can state the same thing about #'cl:update-instance-for-different-class and #'cl:change-class.
At least from a theoretical point of view, CHANGE-CLASS is a simple, natural, and elegant solution to situations where you can't come up with a design that gets behavioral subtyping (LSP) right in all situations.
Simple example: the famous square/rectangle (or circle/ellipse) problem.
(defclass rectangle () ((width :initarg :width :accessor width) (height :initarg :height :accessor height)))
(defun make-rectangle (width height) (if (= width height) (make-instance 'square :width width) (make-instance 'rectangle :width width :height height)))
(defmethod (setf width) :after (width (rectangle rectangle)) (declare (ignore width)) (when (= (width rectangle) (height rectangle)) (change-class rectangle 'square)))
(defmethod (setf height) :after (height (rectangle rectangle)) (declare (ignore height)) (when (= (width rectangle) (height rectangle)) (change-class rectangle 'square)))
(defclass square () ((width :initarg :width :reader width :reader height :accessor side)))
(defun make-square (width) (make-instance 'square :width width))
(defmethod (setf width) (width (square square)) (let ((side (side square))) (unless (= width side) (change-class square 'rectangle :width width :height side))) width)
(defmethod (setf height) (height (square square)) (unless (= height (side square)) (change-class square 'rectangle :height height)) height)
I would hate to see it go. I have 450 new students every year that learn about CHANGE-CLASS :-D