Classes as Packages (was: Harvesting infrastructure)

Andrew P. Black black at cse.ogi.edu
Tue Nov 19 09:41:40 UTC 2002


At 23:55 -0500 11/18/2002, Anthony Hannan wrote:
>	I think that is my whole point: abstract behaviors and traits are
>analogous.

Yes, you've got it!

>So why add a new way of defining behavior and putting
>them together, yielding two types of behaviors and composition in the
>same system.

Why? Because you can't define abstract behaviour in Smalltalk.  That 
is, you MUST specify a superclass when you declare an abstract class. 
Of course, you are not *required* to declare new instance variables, 
but there is no way to restrict programmers from doing so, or from 
accessing inherited instance variables in the supposedly "pure" 
methods.

(OK, you can declare an abstract class with nil as its superclass. 
But try and inherit from it and have things work -- ugh).

So, if you fix those two problems, you get what we call traits. If 
you like, think of traits as lobotomized classes that have
	- no superclass and
	- no state and
	- can't be instantiated.
The compiler will make sure that there is no state and no instance 
variable access.

>  Even in the future work section of the Traits paper, they
>talk about replacing single inheritance and adding state to traits.  This
>would wrap them back around to multiple inheritance but in a nested
>composition form instead of an inheritance form, which would basically
>be the same thing.

This is future work, and highly speculative.  But nesting and 
inheritance are NOT the same thing.  We have used nesting extensively 
in refactoring collections, exactly because it is NOT inheritance. 
The other contribution of traits, apart from the above restrictions 
(are restrictions a contribution?) are the combination operations: 
symmetric composition as well as overriding composition.  We also add 
exclusion and aliasing operations on traits.  Neither is strictly 
necessary, but both are useful.  For example, if you have defined a 
trait that is just what I want but has two extra methods, I could

	(1) ask you to refactor it into two traits, one trait with 
the two extra methods and one trait with the rest, so that I can use 
the second trait and not the first; or
	(2) use it as you provide it, and override the two extra 
methods with "Self shoulNotImplement"; or
	(3) use exclusion to remove the extra methods.

(3) seemed easiest for the programmer.

Aliasing gives the programmer a way of referencing both parties in a 
pair of conflicting methods and writing a combining method.  I 
haven't yet needed to use it, but it's nice to know that it is there; 
it makes the whole thing complete.

>	Finally, I think MI is more conducive to reuse than Traits.  If you
>want to reuse a class that is outside of your single inheritance
>hierarchy, in MI you can just inherit from it, but in Traits you have to
>convert the class to a trait which is difficult if you also want to
>include its inherited behavior.

Converting a class to a trait *would be* difficult if Nathanael had 
not automated it!  One method (executed for you by the browser) will 
convert a class, and as many of its superclasses as you want, into a 
trait.  This was a really powerful tool for us as we refactored 
Collections.

	Andrew






More information about the Squeak-dev mailing list