From: John L. Stein
Subject: How can I define a class which contains another class ?
Date: 
Message-ID: <575g0b$1n94@uni.library.ucla.edu>
How can I define a class which contains another class ?

Can anyone provide a simple example of defclass
where an object contains another object.
I know this is possible in C++ but can't find an example in clos.

Thanks
-js

From: Barry Margolin
Subject: Re: How can I define a class which contains another class ?
Date: 
Message-ID: <576eo4$gle@tools.bbnplanet.com>
In article <···········@uni.library.ucla.edu>,
John L. Stein <·····@seas.ucla.edu> wrote:
>How can I define a class which contains another class ?

CLOS doesn't support embedding one class in another, except via
inheritance.  You can have a slot whose value is an object of the other
class (and use the :TYPE slot option to declare this constraint).

DEFSTRUCT supports this in a limited fashion using the :INCLUDE option.
-- 
Barry Margolin
BBN Planet, Cambridge, MA
······@bbnplanet.com -  Phone (617) 873-3126 - Fax (617) 873-5508
(BBN customers, please call (800) 632-7638 option 1 for support)
From: Howard R. Stearns
Subject: Re: How can I define a class which contains another class ?
Date: 
Message-ID: <329B0FA2.31DFF4F5@elwoodcorp.com>
Barry Margolin wrote:
> 
> In article <···········@uni.library.ucla.edu>,
> John L. Stein <·····@seas.ucla.edu> wrote:
> >How can I define a class which contains another class ?
> 
> >Can anyone provide a simple example of defclass
> >where an object contains another object.
> >I know this is possible in C++ but can't find an example in clos.

Could you tell us more about what you are looking for? Perhaps an
example?


> CLOS doesn't support embedding one class in another, except via
> inheritance.  You can have a slot whose value is an object of the other
> class (and use the :TYPE slot option to declare this constraint).
> 
> DEFSTRUCT supports this in a limited fashion using the :INCLUDE option.

It is not clear to me what is being asked for, and I wouldn't want to
give anyone the idea that there is something one can't do in Lisp! :)

Here are some possibilities:

1. One usual meaning of a "container class" in non-Lisp languages is a
class of objects that hold one or more other objects.  In Common Lisp,
all structures, CLOS objects, general arrays and lists can hold
arbitrary objects of any type.  A simple example is at the end of this
text.

2. People using non-Lisp languages sometimes vary the above to
specifically mean having one object hold a "primitive" object as opposed
to a "reference" object.  In Lisp, there is no distinction - all objects
are "reference" objects.  (There can be a distinction between
"immediate" and "heap allocated" objects in most implementations, but
this doesn't change the discussion here.)  

However, many Lisp implementations convert some kinds of data (such as
fixnums, floats and characters) into direct "machine representations"
internally.  For example, an array specialized to hold base-chars is
very likely to use the equivalent of C char internally within the array.
In general, there is no way for a program to ever see the difference.  I
do not believe most usual CLOS implementations do this for the slots of
the instance.  For example, a slot declared as holding a double-float
probably stores a typicall tagged "reference" double-float "object"
rather than directly storing some IEEE double directly.  However, CLOS
implementations of external databases, etc., probably DO use the machine
representations directly.

In some implementations, a defstruct is more likely to use type
information to store data "directly", but again, this is invisible to
the program.  (This has nothing to do with the :include option.)

3. A class can "include" the definition of another class through
inheritance.  Defclass supports multiple inheritance, defstruct supports
only single inheritance.  This is sometimes refered to as kind-of or
is-a inheritance.

4. Some systems built in Lisp support other notions of inhertance such
as:
  delegation - Attributes and messages not handled by an object through 
   the usual mechanisms are forwarded to another object.
  part-whole - Ex. a car can be a kind-of vehicle -- the class car 
   inherits from the class vehicle.  In addition, the class car could 
   define parts (slots) such as body, drive-train, seats, etc. that are  
   other objects, which may themselves have parts.  This defines another 
   tree  -- a part-whole tree -- in addition to the kind-of tree defined 
   by class inheritence.  Some attributes and messages may be defined to
   be inherited via the part-whole tree as opposed to the kind-of tree.
(The ICAD system by Concentra is one system I happen to be familiar with
that uses both these.)

Do any of these cover what you are looking for?

------------------------------------
Example:

(defstruct my-struct s i f l v o)

(defclass my-class ()
  ((s :initarg :s)
   (i :initarg :i)
   (f :initarg :f)
   (l :accessor my-class-l)
   (v :accessor my-class-v)
   (struct :accessor my-class-struct)))

(let* ((s "a string")
       (i 3)
       (f 4.2)
       (struct (make-my-struct :s s :i i :f f))
       (obj (make-instance 'my-class :s s :i i :f f))
       (v #(nil s i f struct obj))
       (l (list s i f struct obj v)))
  (setf (my-struct-l struct) l
	(my-struct-v struct) v
	(my-struct-o struct) obj
	(my-class-l obj) l
	(my-class-v obj) v
	(my-class-struct obj) struct
	(elt v 0) l)
  (values l v obj struct))