[comp.lang.smalltalk] To Subclass or Encapsulate?

mjohnson@cosmos.acs.calpoly.edu (Mark S. Johnson) (04/24/91)

I've read the access method discussion here with great interest and as
a novice Smalltalker I have learned a lot. I'd like to thank Bill Voss
for his extended answer to my "eyeColor" question. I think in some
vague way that I already knew the answer but was having difficulty
putting it into words. The bottom line for me: any objects that I
build should be much more powerful and much more "active" than mere
"records;" avoiding access methods will help remind me of this.

I have a related style question. (The reason I have these "style"
questions is that I believe that I will be slowly "growing" a series
of applications in my meager spare time; therefore, "style" as it
relates to the ease of maintaining and extending programs is important
to me.)

THE QUESTION:

Say I would like to add a Vector class for mathematical calculations.
I could:

   (1)   create Vector as a subclass of Array and modify/add methods
         (e.g., methods to insure that the elements of a Vector were
         only Numbers, vector multiplication methods, etc)
-OR-
         
   (2)   create Vector as a subclass of Object and "encapsulate" an
         Array inside Vector as an instance variable. That way I could
         more easily protect the underlying Array from messages that I
         don't want it to receive.
-OR-

   (3)   ???

If these questions are too naive for this group please let me know and
I'll just shut up and listen/read.

Thanks to all,
Mark

-- 
Mark S. Johnson        mjohnson@stn9.me.calpoly.edu      (129.65.19.9)

dawg6844@uxa.cso.uiuc.edu (Dan Walkowski) (04/25/91)

mjohnson@cosmos.acs.calpoly.edu (Mark S. Johnson) writes:
>I could:

>   (1)   create Vector as a subclass of Array and modify/add methods
>         (e.g., methods to insure that the elements of a Vector were
>         only Numbers, vector multiplication methods, etc)
>-OR-
>         
>   (2)   create Vector as a subclass of Object and "encapsulate" an
>         Array inside Vector as an instance variable. That way I could
>         more easily protect the underlying Array from messages that I
>         don't want it to receive.
>-OR-


These questions are most definitely not too naive for this group.  These are
important questions, which unfortunately do not have easy answers.  Once again,
it depends on the exact situation.  In other words, what are you going to DO
with your vectors once you have them?  Depending on the answer to that question,
I could make arguments for either answer (1), (2), or (3).  
For example, if you are going to do lots of 'array-like' stuff with your 
vectors, like moving, sorting, and otherwise diddling with individual elements,
then I would probably argue for case number (1).  If, however, you want to
think of your vectors more like 'whole' objects, instead of a collection of
elements, (or if a vector 'contains' other information besides its elements, for
example: a length?  a color?  who knows?)  then I would personally choose
implementation (2).  And, lastly, if the 'main' thing you wish to do with your
vectors were something completely different, say plot them in different colors,
then perhaps it should be subclassed from some graphics object. (?)
Believe me, I almost ALWAYS spend more time deciding how to structure my problem
than actually writing the code.  Why?  Because it makes the code cleaner and
easier to write, and easier to change later.

dan

--
_______________________________________________________________________________
Dan Walkowski                          | To understand recursion, 
Univ. of Illinois, Dept. of Comp. Sci. |   you must first understand recursion.
walkowsk@cs.uiuc.edu                   |

kentb@argosy.UUCP (Kent Beck) (04/25/91)

Re: stupid questions.  Pish and likewise tosh- these are good questions-
witness the volume of wisdom they stimulate...

Re: subclass vs. delegate.  Two questions of varying weight depending on
your programming style, 1) should the subclass respond to all the public
protocol of the superclass and 2) where can I inherit the most implementation?
In the case of Vector I would probably opt to make it a subclass of Number
because I inherit so much, and depending on my masochism level on that 
particular day either have a "bytes" instance variable which would be
bound to an Array or ByteArray, or make the class Vector a byte variable
subclass.  The later wouldn't work as well if vectors changed size dynamically.

If you believe in inheritance as classification you accord more weight to
1) above, and you probably think that Dictionary as a subclass of Set is
a travesty.  If instead you use inheritance as a code sharing mechanism then
2) is more important and SystemDictionary as a subclass of Dictionary makes
no sense.  The Dictionary methods which are inherited are at:, at:put:
and includesKey:.  SystemDictionary adds a hundred or so new methods
which might be better shared from some other class we haven't discovered yet
because we've been staring at the current implementation so long.

So the answer to your question is, of course, it depends.  I generally opt
for maximizing code sharing and I find that the classification dimension
sorts itself out pretty well.  This gives me the ability to organize
inheritance hierarchies mechanically (by asking "which alternative shares
the most code") without letting preconceptions interfere with the best
use of the language's resources.
Kent