From: jimka on
Does anyone have advise for the strategy for writing methods on update-
instance-for-different-class for the case of multiple inheritance.
For example suppose we have the following:

;; library code
(defclass A ()
((a)))

(defclass B ()
((b)))

(defclass C ()
((c)))


;; application code
(defclass X (A B C)
())

(defclass Y (A C)
())

;; application code
(let ((i (make-instance 'Y)))
(change-class i 'X))

(let ((i (make-instance 'X)))
(change-class i 'Y))

In the first case Y --> X the instance is gaining B'ness so this
promotion code can be handled
in the update-instance-for-different-class specializing its second
argument on class B


;; promotion handler
(defmethod update-instance-for-different-class (previous (current B)
&rest initargs)
...)


In the second case X --> Y the instance is going to keep its A'ness
and C'ness
but loose its B'ness. Thus this is sort of a class "demotion". It
appears I can put
this handling in the update-instance-for-different-class method whose
first argument
specializes on B.


;; demotion handler
(defmethod update-instance-for-different-class ((previous B) current
&rest initargs)
...)


There are several things I don't understand about this strategy.

1. Both methods will be called in the case when the old and new
classes BOTH have
B in their class precedence list. So these methods do handle the
promotion and demotion
but not exclusively so.

2. Should I be adding primary methods who call call-next-method, or
should I be adding before/after methods or does it matter?

3. In the case of update-instance-for-redefined-class, the system
passes me structures containing the added and deleted slots. How am I
supposed to get the similar information
in the case of update-instance-for-different-class?

4. Can I really hope to handle all the change-class cases based on
methods specialzin4
on the library classes, A, B, and C, or is it really necessary to
expect the application programmer to handle these by adding methods of
update-instance-for-different-class specialing on X and Y?

Advise from anyone who had done this would be great to have.

-jim
From: jimka on
i think nobody likes update-instance-for-different-class :-(


From: Pascal Costanza on
On 08/07/2010 15:45, jimka wrote:
> Does anyone have advise for the strategy for writing methods on update-
> instance-for-different-class for the case of multiple inheritance.
> For example suppose we have the following:
>
> ;; library code
> (defclass A ()
> ((a)))
>
> (defclass B ()
> ((b)))
>
> (defclass C ()
> ((c)))
>
>
> ;; application code
> (defclass X (A B C)
> ())
>
> (defclass Y (A C)
> ())
>
> ;; application code
> (let ((i (make-instance 'Y)))
> (change-class i 'X))
>
> (let ((i (make-instance 'X)))
> (change-class i 'Y))
>
> In the first case Y --> X the instance is gaining B'ness so this
> promotion code can be handled
> in the update-instance-for-different-class specializing its second
> argument on class B
>
>
> ;; promotion handler
> (defmethod update-instance-for-different-class (previous (current B)
> &rest initargs)
> ...)
>
>
> In the second case X --> Y the instance is going to keep its A'ness
> and C'ness
> but loose its B'ness. Thus this is sort of a class "demotion". It
> appears I can put
> this handling in the update-instance-for-different-class method whose
> first argument
> specializes on B.
>
>
> ;; demotion handler
> (defmethod update-instance-for-different-class ((previous B) current
> &rest initargs)
> ...)
>
>
> There are several things I don't understand about this strategy.
>
> 1. Both methods will be called in the case when the old and new
> classes BOTH have
> B in their class precedence list. So these methods do handle the
> promotion and demotion
> but not exclusively so.
>
> 2. Should I be adding primary methods who call call-next-method, or
> should I be adding before/after methods or does it matter?

To answer such questions, it is important to consider the purpose of
update-instance-for-different-class. It is part of the various ways to
initialize objects, like initialize-instance and reinitialize-instance.
You typically define methods on initialize-instance and
reinitialize-instance to have more complicated initializations of slots
than what you can do with just initargs and initforms. It is also
typically suggested to defined :after methods, both for efficiency and
for ensuring that the object is already "mostly" initialized. There is
actually wording in the description of
update-instance-for-different-class that also "recommends" defining
:after methods here as well, so this seems to confirm what I say.

Usually, I expect update-instance-for-different-class to be specialized
only on its second argument, and use it to only make such complicated
initializations of newly added slots. Then different methods for
u-i-f-d-c will also not interfere with each other.

It's probably also worthwhile to consider defining methods on
shared-initialize instead, unless it really matters.

> 3. In the case of update-instance-for-redefined-class, the system
> passes me structures containing the added and deleted slots. How am I
> supposed to get the similar information
> in the case of update-instance-for-different-class?

The first argument to u-i-f-d-c contains a complete copy of the previous
version of the object to be updated, so you should be able to get all
the necessary information from there.

> 4. Can I really hope to handle all the change-class cases based on
> methods specialzin4
> on the library classes, A, B, and C, or is it really necessary to
> expect the application programmer to handle these by adding methods of
> update-instance-for-different-class specialing on X and Y?

The hope is that every class designer cares about their classes, so you
should only need to define methods for your 'own' classes.

> Advise from anyone who had done this would be great to have.

I don't think the u-i-f-d-c is used a lot, especially because it is
recommended that change-class is not used very often (see the
description for change-class). So I fear that you will likely encounter
problems in this regard when you really want to use change-class with
third-party classes.

But I haven't done a lot with u-i-f-d-c either.


Best,
Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/