Introducing more meaning into inheritance

Mike Klein mike at twinsun.com
Mon Apr 27 19:03:21 UTC 1998


	[Set subclass: #Class]

A lot of the 'trickiness' of this (and the general trickiness of
'mathifizing' CS) is dealing with the notion of 'natural isomorphism'.

In math, liberal use is made of this concept:  There is a natural
isomorpism between:

	cardinal numbers & Ordinal numbers (unified into natural numbers)
	integers & integral fractions (unified via reduction: 42/2 -> 21)
	reals & complex numbers with zero imaginary components

These isomorphisms are so usefull and so natural that we often consider
"forty-two halves" and "twenty-one" to be the "same" mathematical object,
as if the phrase means something formal.  The formal part is making the
isomorphism explicit, and ensuring that, as we ascribe new properties to
these two classes of mathematical objects, the isomorphisms continue to
hold.  This can range from hard (e.g. dealing with division by zero) to
extremely difficult (analytic continuation of real functions to the 
complex plane), to imposible (squaring the circle).

I beleive that the success in math of unifying the above, has given
programmers a false sense of security in the ease of unification.
Witness in Smalltalk (VW):

	(3 at 4) = (3 + 4i)
=>	true

	(3 at 4) squared = (3 + 4i) squared
=>	false

Whomever "unified" Complex and Point has made it so a=b does not imply 
a^2=b^2.

Now let's look at unifying Class and Set.  Let's ignore the fact that
Smalltalk's Sets are vastly different from math's sets.

Should the method Class >># do: action
a)	self allInstances do: action
b)	self allInstances, allSubinstances do: action

The "natural" answer to this, of course, depends on what we are using 
the subclassing mechanism to accomplish, as mentioned in Alan Kay's
earlier post.  Inheritence for implementation wants (a), inheritence for
specialization wants (b).

Some people even view abstract classes as "made up" of their subclasses, so
c)	self allSubclasses do: action


Also, it may make sense for a class to represent all posible
instantiations, not only one's presently in the object memory.
I.e.  
	Integer includes: 10000000000000
=>	true

	Integer size
=>	AlephNull

In the end, we have to ask ourselves:

	"What is a class?"

I will say that the "mathefized" answer is:

	"Classes are sets of ......"

and this leads one off into the same pink areas of convenience that making

	'10' asInteger = 10
or even
	'10' = 10

seem so attracive.
(I'll admit to hacking the former, but not the later :-)
Basicly what we are doing is pressing classes into service of an area that
we already have good mechanisms for, the Collection hierarchy.

A better answer is:
Classes are implementations of objects. Not necesarily the *only*
implementations of objects, but a usefull one.

I think we need to ask ourselves:

"What do we we want classes to become as they head off into the blue?"

I think answers to this question will deal with a richer representation
of metainformation, and a richer ability to manipulate these metaobjects,
in other words, a Meta Object Protocol (MOP).  Being able to represent
inheritence sematics is part of the answer.  Being able to go beyond
static single inheritence in a *controlled* fashion is another.
And so is being able to represent the relationship of a class to its
instances.  But I think that saying classes are kinds of sets is a far
to simplistic answer, and heads one off into the classical math direction,
which is not where classes should be going. There are parts of the code
base that could a more mathematical approach (i.e. the numerics), but I
would not send classes there. (It's to pink for classes).

This is not to say that pink areas of incremental improvement are not
usefull.  I think we just have to ask ourselves, if we do this, what do we
gain, and what do we lose.

-- Mike Klein





More information about the Squeak-dev mailing list