Outline
Other Material
The distinction between subtype and subclass is important because of their relationship to substitution.
Recall the argument that asserted a child class has the same behavior as the parent, and thus a variable declared as the parent class should in fact be allowed to hold a value generated from a child class.
But does this argument always hold true?
What do we mean when we use the term type in describing a programming language?
What about when we consider classes (or interfaces) as a system for defining types?
Consider how we might define a Stack ADT:
interface Stack {
public void push (Object value);
public Object top ();
public void pop ();
}
Notice how the interface itself says nothing about the LIFO property, which is the key defining feature of a stack. Is the following a stack?
class NonStack implements Stack {
public void push (Object value) { v = value; }
public Object top () { return v; }
public void pop () { v = null; }
private Object v = null;
}
So now we can better understand the concept of a subtype.
A subtype preserves the meaning (purpose, or intent) of the parent.
Problem, meaning is extremely difficult to define. Think about how to define the LIFO characteristics of the stack.
It is easy to create a subclass that is not a subtype -- think of NonStack.
It is also possible to create subtypes that are not subclasses. Think of Array in Smalltalk. This class is characterized by the following interface:
at: input put: value at: int size
But class Dictionary will also support the same interface, and perform similar actions -- but Dictionary is not a subclass of Array.
There is a curious paradox that lies at the heart of most strongly typed object-oriented programming languages.
If substitution only makes sense for subtypes and not for all subclasses, why do programming languages based the validity of assignment on subclasses?
It is trivial to determine if one class is a subclass of another.
It is extremely difficult to define meaning (think of the Stack ADT), and even if you can it is almost always impossible to determine if one class preserves the meaning of another.
One of the classic corollaries of the halting problem is that there is no procedure that can determine, in general, if two programs have equivalent behavior.
What does it take to create a subclass that is not a subtype?
Is this common? Not likely. But it shows you where to look for problem areas.