[comp.lang.clos] Non-shared Class Allocated Slots

CORK@cs.umass.edu ("Dan Corkill, COINS, UMass 413/545-0156") (04/04/91)

Neither the macro nor the meta-object approach to creating separate,
class allocated slots for each subclass is suitable when building
modular, layered systems using CLOS/PCL.  For example, suppose I create
a class that is to be used (as a super) to created classes in other
systems/applications.  This super has special "hidden" methods and slots
that are to be inherited by subclasses created by other systems.  Both
the macro and meta-object approach violate the transparency of this
method/slot hiding from a pure class inheritance viewpoint.  Either I
have to remember to use a different defclass macro or to specify a
different metaclass when using the class as a super.  (In the GBB
generic blackboard system, we reluctantly resorted to the macro
approach...)

I strongly believe that CLOS/PCL is missing an important capability with
"class-per-class" allocated slots.  By simply providing a
:CLASS-PER-CLASS allocation specification (along with :INSTANCE and
:CLASS), transparency would be maintained without resorting to macros
and the meta-object protocol.  Implementing the extension is minor
compared to the increased functionality.

gregor@parc.xerox.com (Gregor Kiczales) (04/04/91)

In article <96B8613F4EBF600D38@cs.umass.EDU> CORK@cs.umass.edu ("Dan Corkill, COINS, UMass 413/545-0156") writes:


   Neither the macro nor the meta-object approach to creating separate,
   class allocated slots for each subclass is suitable when building
   modular, layered systems using CLOS/PCL.  For example, suppose I create
   a class that is to be used (as a super) to created classes in other
   systems/applications.

This is an instance of a general problem which can be phrased as: I need
a way for a superclass to affect the class of its subclasses without
going and editing all the defclass forms by hand.  For example, I would
like to define the class TOP and have it and all of its subclasses be
instances of MY-CLASS without having to use the :metaclass option in the
subclass definitions.

(defclass top ()
     ()
  (:metaclass my-class))

(defclass a (top) ())    ;this class should be an instance of my-class

(defclass b (a) ())      ;so should this one

There are two ways to do this using the metaobject protocol.  (In each
case I am describing how to do it using the final version of the
metaobject protocol, if you are using early versions you may need to
tweak this a bit.)

1) If you can get a list of the names of all the subclasses, you can
``pre-define'' those classes with special forward-referenced classes
that, when the real definition comes along, don't go to STANDARD-CLASS
but instead go to MY-CLASS.  That will get you the behavior you are
after I think.

A suitable method on ENSURE-CLASS-USING-CLASS, along with the advance
definitions and a subclass of FORWARD-REFERENCED-CLASS, should be all it
takes.

This technique has been used with success in various MOP-based block
compilers.

2) Another way of addressing the problem is to use VALIDATE-SUPERCLASS
to explicitly let superclasses participate in the selection of the class
of their subclasses.  Something like the following works.

(defclass my-class (standard-class) ())

(defmethod validate-superclass ((sub standard-class)
                                (sup my-class))
  (change-class sub my-class)
  t)

(defmethod validate-superclass ((sub my-class)
                                (sup my-class))
  t)

This needs to be a little more complex to handle forward references, but
the basic idea still applies.

Given either of these mechanisms, the problem of controlling the class
of subclasses can be solved and, given that, the :class-per-class
allocation you mention can be implemented.