[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Slot initializations when changing the class of an instance.



;;; Is there a better way to provide slot initializations when the class 
;;; of an instance is changed via change-class?  What I would really like 
;;; is for change-class to accept a list of initargs, similar to 
;;; make-instance.  I am using the following kludge:

(defvar *INITARGS* nil "Temporary global")

(defclass CLASS-CHANGEABLE-OBJECT () ()
  (:documentation "The CLASS-CHANGEABLE-OBJECT is a class hook which will 
allow instances to be initialized when their class is changed."))


(defmethod update-instance-for-different-class :around
	   ((previous CLASS-CHANGEABLE-OBJECT) current &rest initargs)
  (declare (ignore initargs) (special *INITARGS*))
  ;; Initargs are read from the def... form.
  (apply #'call-next-method previous current *INITARGS*))


(defclass OLD-CLASS
    (CLASS-CHANGEABLE-OBJECT)
    ((slot1
	:initarg :s1
	:initform 0
	:accessor s1)))


(defclass NEW-CLASS
    ()
    ((slot1
	:initarg :s1
	:initform nil
	:accessor s1)
     (slot2
	:initarg :s2
	:initform (very-time-consuming-computation 2)
	:accessor s2)
     (slot3
	:initarg :s3
	:initform (very-time-consuming-computation 3)
	:accessor s3)))

(setq instance (pcl::*make-instance 'old-class :s1 99))
(describe instance)
#<OLD-CLASS 30322061> is an instance of class #<Standard-Class OLD-CLASS 26765401>:
 The following slots have :INSTANCE allocation:
 SLOT1    99

;;; Now to change the class of instance.
(let ((*INITARGS* (list :s2 2 :s3 3)))
  (change-class instance 'new-class))

(describe instance)
#<NEW-CLASS 30322061> is an instance of class #<Standard-Class NEW-CLASS 26330021>:
 The following slots have :INSTANCE allocation:
 SLOT1    99
 SLOT2    2
 SLOT3    3


;;; What would be nice is for:
;;; (change-class instance 'new-class :s2 2 :s3 3)
;;; to accomplish the same thing.  Because it might be costly
;;; for the newly added local slots to be initialized to their
;;; :initform's, I want to inject initargs into the primary 
;;; update-instance-for-different-class method.  But I don't 
;;; like the idea of using a global variable for temporary 
;;; storage.  Why is it that the change-class method does not 
;;; accept initargs?
;;;
;;; Thanks, 
;;; Darrell Shane