From: Brian Denheyer
Subject: instances of classes and instances of instances
Date: 
Message-ID: <87iubzbtyg.fsf@soggy.deldotd.com>
I have run into this design "problem" several times and I have a
nagging feeling I'm not handling it correctly :

Let's say you have created a class which is to act as a "template" for
other instances.  I'm going to use an inventory like system as my
example :

(define-class <widget> ()
 (width
  height 
  color
  cost
  name
  ...
  instance-identifier
  complicated-structure))

So now <widget> is described, but I want to have many instances of
widget in my program, each distinguished by the content of their
slots, not by the name of their class.  For example if <widgets> are
cubes, I will distinguish between red-cubes, blue-cubes, etc...
complicated-structure might be something really ugly, like a JPEG of a
pattern which appears on the outside of the cube.

The thing is, if I just create instances of <widget> I'll end up with
instances which all have their own copy of complicated-structure.  For
that matter they will all have their own copy of all the slots, when,
in fact, they should all share the same information.  A particular
instance of <widget> is what I call a "template".  So to avoid all
this duplication of information, I've been doing this:

Remove the identifier slot from widget and create the following class:

(define-class <widget-instance> ()
  (widget ;; a reference to the "template" instance
   identifier))

Now I create an instance of <widget-instance> based on a widget of a
particular "construction".  The widget slot points to reference of an
instance of <widget>.  So I would have instances of <widget-instance>
blue-cube-1, blue-cube-2, etc. which all share a "blue-cube" instance
of class <widget>.  Still with me ? The information is now shared
across multiple widgets of the same "type" and I have what I call an
instance of an instance (or an instance of the template).

The things that really bugs me is that data accesses now must go
through another level of indirection.  I have to operate on a slot of
the widget-instance instead of on the widget-instance itself even
though my intention is to have, in a way an instance of <widget>.

So, am I missing something ?  For someone reason this design approach
doesn't feel right.  I have noticed this pattern in both C++ and CLOS
programming and I am thinking that there is probably a better way to
do what I am trying to do.  Naturally I'm interested in the best way
using CLOS.


Brian

From: Tim Bradshaw
Subject: Re: instances of classes and instances of instances
Date: 
Message-ID: <nkj90cvqgfh.fsf@tfeb.org>
Brian Denheyer <······@deldotd.com> writes:


> The thing is, if I just create instances of <widget> I'll end up with
> instances which all have their own copy of complicated-structure.  For
> that matter they will all have their own copy of all the slots, when,
> in fact, they should all share the same information.  A particular
> instance of <widget> is what I call a "template".  So to avoid all
> this duplication of information, I've been doing this:
> 
> Remove the identifier slot from widget and create the following class:
> 
> (define-class <widget-instance> ()
>   (widget ;; a reference to the "template" instance
>    identifier))
> 

You can use class slots to do this, though they don't always work as
you'd want I think (in particular in the context of subclassing).  In
general this looks pretty close to the `flyweight' pattern that the
design patterns people talk about.  I forget how they think you should
do this.  I'm hoping to do a CLOS-take on the `gang-of-four' design
patterns book, so if you wait for that ...

--tim
From: Christopher J. Vogt
Subject: Re: instances of classes and instances of instances
Date: 
Message-ID: <36F111C2.DAF31208@computer.org>
Brian Denheyer wrote:
>[...]
> 
> So now <widget> is described, but I want to have many instances of
> widget in my program, each distinguished by the content of their
> slots, not by the name of their class.  For example if <widgets> are
> cubes, I will distinguish between red-cubes, blue-cubes, etc...
> complicated-structure might be something really ugly, like a JPEG of a
> pattern which appears on the outside of the cube.
> 
> The thing is, if I just create instances of <widget> I'll end up with
> instances which all have their own copy of complicated-structure.  

They won't have their own copy of compilicated-structure, they will each
have their own "pointer" to the same object.  If compilicated-strucuture
is some 5MB representation of a JPEG image, then each instance has a pointer
to the same image, the 5MB isn't duplicated in each instance, only the
pointer is duplicated.

>[...]
>
> So, am I missing something ?  For someone reason this design approach
> doesn't feel right.  I have noticed this pattern in both C++ and CLOS
> programming and I am thinking that there is probably a better way to
> do what I am trying to do.  Naturally I'm interested in the best way
> using CLOS.

maybe you could do something like this:
(defvar *compilicated-structure* nil)

(defclass widget()
  (complicated-structure))

(defmethod initialize-instance :after ((self widget) &key)
  (with-slots (complicated-structure) self
    (if (null *compilicated-structure*)
	(setf *compilicated-structure* (make-complicated-structure)))
    (setf complicated-structure *compilicated-structure*)))


(defun make-complicated-structure ()
  (make-array 10000))