Recall the toggle class with method switch we discussed previously:
define class (
Consider further the following button class and its method press:
define class
What will happen if we evaluate each of the following:
define variable t = make ();
define variable b = make (
Note how collecting together an action and object into a button provides
an extremely general mechanism for issuing commands from a button.
Since switch is a generic function, what will happen to the button
if I were to redefine the switch method for toggles to have some other
behavior? Would the button reflect this change or not?
Inheritance
When inheritance is employed, behavior and data associated with the
derived class are always an extension of the
properties associated with the base class.
The representational complexity of a derived class is therefore
greater than that of its base class, however, the number of objects
and their generality is strictly not greater than its base class.
Inheritance Benefits
Software Reuse
Code Sharing
Interface Consistency (assuming adherence to manifest
semantics and no overriding)
Polymorphism
Polymorphism - What is it?
Polymorphism (pol - many, morph - shape)
A feature of programming languages supporting the ability of
one segment of code to behave in different ways on different
types (shapes) of objects. The behavioral specification is
given by using behavioral interfaces to which the objects must
subscribe, but each object may tailor its implementation of the
interface to its own specifications.
Dylan, for example, provides a hierarchy of
<collection> classes. There is an iteration
protocol that each of the <collection>
classes must subscribe to (by providing a method called
forward-iteration-protocol, which behaves in
a class-specific manner. As with all code supporting
polymorphism, the interface is agreed to at a high level, then
each class provides its own implementation of the required
behavior.
Is inheritance costly?
C++ and other languages have demonstrated that inheritance can
be provided at almost no extra cost in execution speed or program
size. If a language supports extra capabilities on top of
inheritance alone, however, costs can increase.
Program complexity can be increased without bound by poor programming
practice that employs inheritance in overly obtuse ways.
When should one subclass?
Specialization
This is the normal justification for creating a subclass.
I have a window class, but now I need a special kind of
window called a menu.
Many problems present choices and no clear-cut inheritance
structure.
Specification
Budd notes that some classes, which he calls
specification classes, are abstract, and are
provide interface specifications for concrete classes
that will be derived from them. I think again of the
<collection> class of Dylan and some of its subclasses
like <mutable-collection> and
<sequence>. These classes do not have direct
instances.
Combination
This is employed in multiple inheritance systems to combine the
features of two dissimilar classes. The example of pg. 95
shows TeachingAssistant being derived from
both Teacher and Student.
A common type of combination is the use of mix-in classes,
which derives its name from Steve's Ice Cream Parlor in Somerville
Massachussetts which would mix-in various goodies (such
as chocalate chips, Reese's pieces, Gummy Bears, etc.) with
ice cream. A mix-in class provides some specific capability that
complements the behavior of any class that derives from it.
Consider a class Displayable that might provide
a specific behavioral interface, and a class Counter.
We might create DisplayableCounter by deriving from
both of these classes.
Composition vs. Construction
I prefer to discuss this issue in terms of inheritance and
aggregation, the mechanisms that are employed.
Budd provides an example in which a class SymbolTable
may either be derived from class Dictionary, or have
a Dictionary object as an aggregate element.
Dictionary objects exhibit behaviors
atKey: (which looks up the value associated with a key
by the Dictionary receiver) and
atKey:put: (which causes an association to occur in
the Dictionary receiver.
The SymbolTable class associates only string values
with string keys. It accepts messages lookup:
and add:value:.
Budd notes pros and cons of using inheritance or aggregation.
I will flatly state that I prefer the use of aggregation in this
case due to the following arguments:
Inheritance does not prevent users from employing
atKey:put: and possibly violating the
representation invariants maintained by
SymbolTable objects.
Exploration of this problem is appropriate in answers to
question 4 on pg. 101.