Subtyping (design methodology)
- stepwise refinement by specialization
Specialization -- conceptual hierarchies
Implementation -- to realize a supertype
Combination -- multiple inheritance
Non-standard subtyping:
Generalization -- Win -> ColorWin
Variance -- Mouse -> Tablet [Pointing]
Limitation -- Deque -> Stack
Creativity and clear headed thinking are the most important ingredients of design!
slide: Design methodology
As we have seen previously, subtyping may be
used to realize a partially defined (abstract) type,
or as a means with which to add a specialization to a conceptual
hierarchy.
On a number of occasions, however, the need may arise
to employ what [HOB87]
called non-standard subtyping,
and which is also known as non-strict inheritance.
An example of non-strict inheritance is a derivation
that results in a generalization,
as occurs, for instance, when deriving a colored window
class from a base class window (supporting only
black and white).
We speak of a generalization since the type associated
with colored windows properly encompasses the collection
of black and white windows.
Yet from an implementation perspective, it may be convenient
to simply extend the code written for black and
white windows, instead of redesigning the class hierarchy.
Another example of non-strict inheritance is
when the derivation results in what may be called
a variant type, which occurs, for instance,
when deriving a pen or tablet class
from a class defining the behavior of a mouse.
The proper course of action in such cases is to
introduce an abstract class pointing device
from which both the mouse and tablet
classes may be derived (as proper subtypes).
Another, equally evident, violation of the subtyping
regime occurs when restricting a given class
to achieve the functionality belonging to the type of
the derived class.
A violation, since the requirement of behavioral
conformance demands that either new behavior is added
or already existing behavior is refined.
Actual limitation of behavior results in a behaviorally
incompatible class.
The standard example of limitation, originally given in [Snyder86],
is the restriction of a double ended queue into
a stack.
A better, and from a type perspective, perfectly legal
solution is to derive a stack from a double ended queue
by using private inheritance.
However, from a design perspective, the use of
private inheritance must be considered ill-practice,
since dependencies may be introduced in the object model
that remain invisible in a more abstract (type oriented)
description of the system.
Delegation, as in the handler/body idiom described
in section [2-handler], is to be preferred
in such cases since it makes the uses
relation explicit and does not compromise the type
system.