best way of assigning slot values from parent class instances to child class instances

best way of assigning slot values from parent class instances to child class instances

Post by Stormcode » Thu, 11 May 2006 06:40:58


I have two classes one subclasses the other. What is the best way of
assigning slot values from a parent class instance to a child class
instance. Right now I am just assigning each slot with setf. Is there a
better way of doing that?
 
 
 

best way of assigning slot values from parent class instances to child class instances

Post by Pascal Bou » Thu, 11 May 2006 08:59:12

Stormcoder" < XXXX@XXXXX.COM > writes:

So you have:

(defclass animal ()
())

(defclass bird (animal)
(wings))

and you'd want to do:

(defmethod do-something ((self animal))
(setf (slot-value self 'wings) (list 'left 'right)))

?

How do you justify it?

What would happen with:

(defclass cat (animal)
(legs))

(do-something (make-instance 'cat))

?


You could have an abstract operation thought:

(defclass animal ()
())

(defgeneric add-member (animal member))


(defclass member ()
())
(defclass wing (member)
((span :initform 5)))
(defclass leg (member)
((length :initform 10)))
(defclass arm (member)
((strength :initform 8)))


(defclass bird (animal)
((wings :initform nil) (legs :initform nil)))

(defmethod add-member ((self bird) (member wing))
(push member (slot-value self 'wings)))

(defmethod add-member ((self bird) (member leg))
(push member (slot-value self 'legs)))

(defclass snake (animal)
())

(defmethod add-member ((self snake) (member t))
(error "A snake takes no member!"))

(defclass monkey (animal)
((arms :initform nil) (legs :initform nil)))

(defmethod add-member ((self monkey) (member arm))
(push member (slot-value self 'arms)))

(defmethod add-member ((self monkey) (member leg))
(push member (slot-value self 'legs)))

(defclass cow (animal)
((legs :initform nil)))

(defmethod add-member ((self cow) (member leg))
(push member (slot-value self 'legs)))



But with CLOS you could use multiple inheritance:

(defclass member () ())
(defclass wing (member) ((span :initform 5)))
(defclass leg (member) ((length :initform 10)))
(defclass arm (member) ((strength :initform 8)))


(defgeneric add-member (animal member))

(defclass winged-body () ((wings :initform nil)))
(defmethod add-member ((self winged-body) (member wing))
(push member (slot-values self 'wings)))

(defclass legged-body () ((legs :initform nil)))
(defmethod add-member ((self legged-body) (member leg))
(push member (slot-values self 'legs)))

(defclass armed-body () ((arms :initform nil)))
(defmethod add-member ((self armed-body) (member arm))
(push member (slot-values self 'arms)))



(defclass animal () ())

(defmethod add-member ((self animal) (member t))
(error "An ~A doesn't take a ~A"
(class-name (class-of self))
(class-name (class-of member))))

(defclass bird (animal winged-body legged-body) ())
(defclass monkey (animal armed-body legged-body) ())
(defclass cow (animal legged-body) ())
(defclass snake (animal) ())


In both case, you can use the "abstract method" from a general method:

(defmethod do-something ((self animal) (member-class symbol))
(add-member self (make-instance member-class)))

--
__Pascal Bourguignon__ http://www.informatimago.com/
Small brave carnivores
Kill pine cones and mosquitoes
Fear vacuum cleaner

 
 
 

best way of assigning slot values from parent class instances to child class instances

Post by tar » Fri, 12 May 2006 03:21:25

"Stormcoder" < XXXX@XXXXX.COM > writes:


I don't quite understand what you are trying to do.
Could you perhaps give an example?


--
Thomas A. Russ, USC/Information Sciences Institute
 
 
 

best way of assigning slot values from parent class instances to child class instances

Post by Stormcode » Sun, 14 May 2006 05:38:47

What I am trying to do is understand the lispy idioms for doing certain
things. In this case I'm trying to determine if there is a more lispy
way of assigning field values from one object to another, other than
member wise assignment. In C++, the default for two objects of the same
class when one is assigned to another is a memberwise copy (which is
bad for pointer members). You can create copy contructors and overload
the assignment operator to get the right behavior.
(The above is just example so no comments on the viability of C++)

ie. I've got an Auto class with some basic automobile functionality. I
have a Pickup sub-class of Auto. I've been doing some operations on an
Auto object and I want to use the Auto object to initialize a Pickup
object. (Might not be an initialization but could be an assignment or
something) The obvious way is just to have a method that does a member
wise assignment of fields.

The question is, is that the idiomatic way of doing this or is there a
better way?

Another question that occured to me is, Is there the equivalent of a
cast, in this case from pickup to auto and back?
C++ equivalent of:

hAuto &auto = dynamic_cast<Auto&>(pickup);
 
 
 

best way of assigning slot values from parent class instances to child class instances

Post by Bill Atkin » Sun, 14 May 2006 06:17:26

"Stormcoder" < XXXX@XXXXX.COM > writes:


(let ((my-pickup (make-instance 'auto :make 'ford :model 'f150)))
(change-class my-pickup (find-class 'pickup)))

assuming PICKUP is a subclass of AUTO.


CHANGE-CLASS?
 
 
 

best way of assigning slot values from parent class instances to child class instances

Post by Tayssir Jo » Sun, 14 May 2006 22:05:33


Are you looking for something like the following?

;; requires metaobject protocol
(defmethod copy-slots (from to)
"For the slots the two objects have in common, copy slot values from
FROM to TO.

Returns TO."
(let* ((from-class (class-of from))
(to-class (class-of to))
(from-slots (mapcar #'slot-definition-name
(class-slots from-class)))
(to-slots (mapcar #'slot-definition-name
(class-slots to-class))))
(loop for name in (intersection from-slots to-slots)
do (setf (slot-value to name)
(slot-value from name)))
to))

(defun make-prototype (super subclassname)
"Makes an instance of class named by SUBCLASSNAME, and initializes it
with SUPER's slot values."
(let ((new-instance (make-instance subclassname)))
(copy-slots super new-instance)))


Tayssir
 
 
 

best way of assigning slot values from parent class instances to child class instances

Post by Tayssir Jo » Mon, 15 May 2006 03:26:13


Hmm, making that code less verbose and specific...

(defmethod slot-names (object)
(mapcar #'slot-definition-name (class-slots (class-of object))))

(defmethod copy-slots (from to)
(loop for name in (intersection (slot-names from) (slot-names to))
do (setf (slot-value to name) (slot-value from name))
finally (return to)))

(defmethod make-prototype (object new-classname)
(copy-slots object (make-instance new-classname)))


Tayssir
 
 
 

best way of assigning slot values from parent class instances to child class instances

Post by Stormcode » Mon, 15 May 2006 12:51:58

This is what I was looking for.