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

Re: Class explosion

Your message is not entirely clear to me.  What I hear you are saying is
that you have a large number of mixins, and you don't want to define the
full `cross product' of classes up front.  Furthermore, you would like
to be able to change the `class' of instances easily.  You want to be
able to take an instance and cause it to have some behavior from a mixin
that it didn't have before.

This is easy to do in PCL.  You need to use some simple metaobject level
functionality.  You want to be able to create classes, on the fly, given
a list of superclasses.  Given that, it is easy to build a facility that
adds a mixin to an object simply my making a new on-the-fly class and
changing the class of the object.

Here is some code can you can use.  This code will need some tuning to
fit your particular style of using it.  In particular, you want to be
sure not to create a bunch of dynamic classes each of which have exactly
the same class precedence list.  You may want to work on add-mixin to
achieve this.  I can help you with that if you like.

One last comment is that the definition of find-dynamic-class below will
need to be tweaked slightly in a future release of PCL.  But, the change
will minor so it is OK for you to depend on this code.

;;; Note, these functions accept class objects, not class names.
;;; You must call FIND-CLASS on the name before calling these
;;; functions.
(defvar *dynamic-classes* ())

(defun find-dynamic-class (superclasses)
  (or (find superclasses *dynamic-classes* :key #'class-local-supers )
      (let ((new (make-instance 'standard-class)))
	(update-class new :direct-superclasses superclasses)
	(push new *dynamic-classes*)

(defun add-mixin (object mixin-class)
  (let ((class (class-of object)))
    (if (memq mixin-class (class-precedence-list class))
	(error "The class of ~S already includes ~S." object mixin-class)
	(change-class object
		      (find-dynamic-class (list mixin-class class))))))