[FIX] IsKindOfForm-nk ( An honest question )
Richard A. O'Keefe
ok at cs.otago.ac.nz
Wed Apr 21 06:32:44 UTC 2004
frank at crystal-objects.com asked:
As a squeak newbie I'm curious why the standard isKindOf: is not
considered correct or workable and we have added all these 'isWhatevers'
to object? A quick look at object shows about 27 special form tests
added. isWebBrowser, how often does that get called?
Do we have a FAQ somewhere for Squeak? This ought to be on it.
The problem is that isKindOf: answers the wrong question.
It is important to distinguish between the "SUBTYPE" relationship between
classes (X is a subtype of Y if and only if you can use an instance of X
wherever an instance of Y is required) and the "INHERITS-FROM" relationship
between classes (X inherits from Y if and only if it was so declared).
Some OO languages provide both these concepts explicitly.
C++ has fairly weak support for this: if Y is a private base class of X,
then X inherits-from Y but X is *not* a subtype of Y.
Eiffel recently acquired the ability to inherit from a class without
implying subtyping, or so I believe.
Even Java makes a distinction: a class or interface can be a SUBTYPE
of an interface, but you can't INHERIT-FROM an interface (well, you can
inherit constants, but you cannot inherit methods or instance variables).
Smalltalk has a very clear distinction between the two concepts, but
supports only one of them. In Smalltalk, the design equivalent of a
"type" is called a "protocol". A protocol is a set of message selectors
with an agreed meaning. In the ANSI Smalltalk standard, the core protocols
are explicitly named, and there is a multiple "inheritance" relationship
Classes IMPLEMENT protocols.
Classes INHERIT methods and instance variables from classes.
Protocols can be SUBTYPEs of other protocols.
What you normally want to know is NOT "how is this class composed from
other classes" but "does this object support that protocol"?
There are two major problems with isKindOf:
(1) It says NO too often. For example, suppose I want to send messages
#includes: and #add: to an object. In Smalltalk, two classes
can both implement a protocol (in this case, one of the collection
protocols) WITHOUT sharing a common ancestor where those selectors
are declared. If I ask whether x isKindOf: Collection, then I am
going to be misled about objects that DO implement the messages I
care about (are instances of a SUBTYPE of collection, in other words)
but happen not to INHERIT-FROM Collection.
Consider XML, for example. An interesting question about an object
is "can I make this a child of an XML element?" In my library, the
answer was "yes" for my own XML classes, of course, but it was also
"yes" for Strings and Symbols, which did NOT inherit from any of my
(2) It says YES too often. Suppose I do "x := Array new: 10."
Then x isKindOf: Collection, but it DOESN'T support the #add: message.
(More precisely, it does implement it, by always reporting an error.)
Both of these problems boil down to answering the wrong question.
A fundamental thing about programming in Squeak is "ask the question you
really mean". "Can I add this to an XML element", not "is this an instance
of a class that inherits from XmlObject". "Does this support the stream"
protocol, not "is this an instance of a class that inherits from Stream".
(There are good reasons to have your own streams that don't inherit from
You try not to go wild inventing is... methods, and you try to put them
as far towards the leaves of the class hierarchy as you can, but at the
end of the day, the important thing is to ask the question you really want
an answer to, not some other question that happens to be easier to ask.
More information about the Squeak-dev