From: kanderso@bbn.com
Subject: Re: Implementation Question
Organization: The Ohio State University Department of Computer and Information Science
Date: Thu, 3 Sep 1992 06:20:59 GMT

  To: comp.lang.clos@cis.ohio-state.edu
  Date: Wed, 2 Sep 1992 23:58:04 GMT
  Organization: School of Mathematics and Statistics, University of Sydney
  From: Graham Matthews <graham@maths.su.oz.au>
  Sender: commonloops-request@cis.ohio-state.edu
  References: <graham.715435125@galois>, <9209021511.AA29151@news.cis.ohio-state.edu>u
  Subject: Re: Implementation Question
  
  ...

  kanderso@bbn.com writes:
  >But there must be some A behavior that B needs, otherwise B would not need
  >to be a subclass of A.  It sounds like you want your B class to inherit
  >from a class "essential A" which has the A behavior you need, without the slots.
  
  No not really. The example I have in mind is a module and an abelian
  group. Now a module *is* an abelian group, but one hardly ever computes 
  with it as such - users are aware of the is-a relationship but hardly
  ever make any use of it. They always want to compute with modules and
  sub-types of it such as vector spaces, and are not at all interested
  in its abelian group structure.
  
Doug Morgan's suggested approach of using an abstract class does what you
want here.  It lets you represent the IS-A relationship, without further
implementational overhead. Right?

  graham
  >  b) I have example code where the representation of B is not the
  >  same as A. That is mathematically B is a sub-type of A but for
  >  various reasons the implementation of B does not have any of the 
  >  slots of A.
  >  
  kanderso@bbn.com writes:
  >You can separate the "mathematical subtypeness" from implementation using
  >a level of indirection:
  >class A
  >       instance variables implementation;
  >end class;
  >class B
  >       subclass of A;
  >end class;
  >A's and B's can forward to an object in instance variable implementation
  >that implements the real behavior.
  
  I am not sure I understand what you mean here. What do you mean by
  "forward to an object in instance variable implementation"?

Basically, we let the implementation iv be an object that does the work,
either by forwarding or by delegation.  In CLOS this might look something
like:

(defclass a
 ((implementation :initarg :implementation
                  :initform (make-instance 'a-implementation)))
 ())

(defclass a-implementation ... ) ; The real a behavior we want to implement.

(setq an-a (make-instance 'a))

Say that A's have a generic function, M, that does something.  We can
define M to either forward, or delegate to IMPLEMENTAION as follows:

(defmethod m ((a a))
  ;; Forward to implementation
  (m (slot-value a 'implementation)))

(defmethod m ((a a-implementation)) ...)

(defmethod m ((a a))
  ;; Delegate to implementation
  (m-internal (slot-value a 'implementation) a))

(defmethod m-internal ((i a-implementation) (a a))
  ...
  (m-1 a))

Using forwarding, the state and behavior of an A actually comes from
IMPLEMENTATION.  Using delegation, the behavior of an A comes from both the
A and its IMPLEMENATION.  Changing IMPLEMENTATION would change the A's
behavior.  Another way to do this would be to use CHANGE-CLASS as Barmar
suggested, in languages that support it.
Newsgroups: comp.lang.clos