ood and inheritance (chapter 5 in text). designing with inheritance inheritance: the ability to...
TRANSCRIPT
Designing With Inheritance
Inheritance: the ability to define new classes as refinements or extensions of previous ones
Inheritance is a central feature of OOD and OOP because:
1. Simplifies programming
2. Allows code to be reused through sharing
3. Can refine and extend code through virtual methods.
Example: Stacks and Queues
Front Rear
Items enterhere
Items exithere
Top
Items both enter and exit here
Stack as a Variation of Queue
Front Rear
Items enterhere
Items exithere
Front
Items enterhere
Items exithere
New Terminology
Conceived this way, stacks and queues differ only in where items enter
So we will call an ordinary queue a rear queue since items enter at rear First-in, First-out (FIFO)
We will call a stack a front queue since items enter front Last-in, First-out (LIFO)
Generalization Class Diagram
We will say that front queues and rear queuesare extensions (derived subclasses) of a general queue class:
Queue
FrontQueue RearQueue
Attributes (Data) in Common
What attributes do stacks (front queues) and queues (rear queues) have in common? An underlying structure (for example, an array) A place where items are added (for example, an
index) A place from which items are removed
Operations in Common
What operations do stacks and queues have in common (regardless of how the operations are implemented)? Create Add an item Remove an item Check for emptiness Check for fullness Display
Generalization Diagram Again
Queue
maxSize: Integerfront: Integerrear: Integer
display(): voidadd(Item): voidremove(): Itemempty(): Booleanfull(): Boolean
FrontQueue RearQueue
Item
*items
1
Abstract Classes
The Queue class is conceived to be what is common to both the FrontQueue and RearQueue classes
It makes no sense to make an object of type Queue; it is abstract (name in italics)
Operations in italics are abstract, like place holders; they must be overridden by the extending classes FrontQueue and RearQueue
The FrontQueue and RearQueue classes inherit data attributes from Queue
PolymorphismPolymorphism is the ability of a language to determinewhich operation to use among many of the same name.
Simple examples performed statically at compile time: - type conversion - operator overloading - function overloading by parameter and return types
Pure polymorphism is the ability to choose amongoperations of the same name dynamically at run time.
In C++, pure polymorphism is achieved throughinheritance and virtual functions.
An Abstract QueueInfo Class in C++
class QueueInfo {protected: ItemArray items; Integer maxSize; Integer front; Integer rear; public: QueueInfo(Integer size); ~QueueInfo(); void add(ItemArray newItems, Integer numItems); virtual void display(); virtual void add(Item item) =0 ; virtual Item remove() =0 ; virtual Boolean empty() =0 ; virtual Boolean full() =0 ; };
Notes on the QueueInfo Class
The protected keyword has the same meaning as private, except that protected data is accessible to class extensions (subclasses)
The virtual keyword on a method without the =0 body means the method may be overridden by subclasses
The virtual keyword on a method with the =0 body means the method must be overridden by subclasses (pure virtual method)
Notes on the QueueInfo Class (cont'd)
The QueueInfo constructor is not virtual, and will be shared by RearQueueInfo and FrontQueueInfo objects
Must be implemented by QueueInfo class
The add method is overloaded: The non-virtual version will be shared and must be
implemented by QueueInfo class The virtual version must have separate definitions in
both RearQueueInfo and FrontQueueInfo classes
The Difference Between Overloading and Overriding
Suppose q is of type FrontQueue. Consider: q->add(itemArray, numItems); q->add(item);
The difference between these two calls can be determined by the compiler on the basis of the calls' signatures
This is an example of method overloading Also called ad-hoc polymorphism
The Difference Between Overloading and Overriding (cont'd)
Suppose q is of declared type Queue. Consider: q->add(item);
Since the one-parameter add method is only defined for FrontQueues and RearQueues, which method does this refer to?
Answer: can only be determined at run-time by looking at the specific type for q
This is an example of method overriding Also called pure polymorphism
Pure Polymorphism Example
class CommandInterpreterInfo {private: Queue q; // either a RearQueue or FrontQueue Character cmd; // queue command: c, a, r, or d Character qtype; // queue type: r or f Integer qsize; // queue size . . .public: CommandInterpreterInfo(); void execute(); // run this command interpreterprivate: . . . void processCreate(); // process a cr or cf command void checkEOF(); // check for premature EOF . . .};
Pure Polymorphism Example (cont'd)
void CommandInterpreterInfo::processCreate() { if (cmd != 'c') { <error: first command must be create> } cin >> qtype; checkEOF(); if ( (qtype == 'f') || (qtype == 'r') || (qtype == 'p') ) { cin >> qsize; checkEOF(); switch ( qtype ) { case 'f': q = new FrontQueueInfo(qsize); cout << "Front"; break; case 'r': q = new RearQueueInfo(qsize+1); cout << "Rear"; break; case 'p': . . . } cout << " Queue Created of Size " << qsize << endl; } else { <error: bad queue type> }}
QueueInfo Constructor QueueInfo objects are not explicitly
constructed using new However, a QueueInfo constructor can be
defined as what is common between FrontQueueInfo and RearQueueInfo:
QueueInfo::QueueInfo(Integer size) { maxSize = size; items = new Item[maxSize]; for (Integer i = 0; i < maxSize; i++) { items[i] = NULL; }}
Defining Subclasses in C++:Example
class FrontQueueInfo : public QueueInfo {public: FrontQueueInfo(Integer n); void add(Item item); Item remove(); Boolean empty(); Boolean full(); void display();};
Similarly for RearQueueInfo
Notes on the Example
The ``: public QueueInfo'' construction means that FrontQueueInfo is to inherit all public and protected methods from QueueInfo
FrontQueueInfo has its own constructor to supplement that ``inherited'' from QueueInfo
FrontQueueInfo has a display method, even though it doesn't have to
Subclass Constructors
Constructors for subclasses indicate in their headerswhich parent class constructor to use:
FrontQueueInfo::FrontQueueInfo(Integer n): QueueInfo(n) { < code to initialize a new front queue >}
RearQueueInfo::RearQueueInfo(Integer n): QueueInfo(n) { < code to initialize a new rear queue >}
Non-Pure Virtual Methods
The display method in the QueueInfo class is virtual, but not pure
Thus, it has a definition in the QueueInfo class:
void QueueInfo::display() { for (Integer i = 0; i < maxSize; i++) { if ( items[i] == NULL ) cout << " ___" ; else items[i]->display(); } cout << endl;}
Non-Pure Virtual Methods (cont'd)
If a subclass does not override a nonpure virtual method, then its parent's definition will be used
In the display example, the parent definition simply dumps out the contents of the array
This is not how the final display is supposed to look for the assignment, but it can be used for debugging
If a subclass does override a virtual method, the method for the most specific type is used
Inheritance and Separate Compilation
When a subclass and its parent class are in separatemodules, the subclass module must be remadewhenever the parent class module is.
Makefile:
RearQueueInfo.o: QueueInfo.o RearQueueInfo.cc ...<TAB>g++ -c RearQueueInfo.cc -o RearQueueInfo.o
Failure to do this can cause bizarre behavior.
Inheritance Pitfalls (;-)Mutant Marsupials Take Up Arms Against Australian Air Force
As virtual reality simulators assume larger roles in helicopter combat training, programmers have gone to great lengths to increase the realism of their scenarios, including detailed landscapes and - in the case of the Northern Territory's Operation Phoenix- herds of kangaroos (since disturbed animals might well give away a helicopter's position).
The head of the Defense Science & Technology Organization's LandOperations/Simulation division reportedly instructed developers tomodel the local marsupials' movements and reactions to helicopters.
Inheritance Pitfalls (cont'd)
Being efficient programmers, they just re-appropriated some codeoriginally used to model infantry detachment reactions under thesame stimuli, changed the mapped icon from a soldier to a kangaroo,and increased the figures' speed of movement.
EnemyInfantrypositiontypespeedarmament
. . .
Kangaroo
Inheritance Pitfalls (cont'd)
Eager to demonstrate their flying skills for some visiting Americanpilots, the hotshot Aussies "buzzed" the virtual kangaroos in lowflight during a simulation.
The kangaroos scattered, as predicted, and the visiting Americans nodded appreciatively... then did a double-take as the kangaroos reappeared from behind a hill and launched a barrage of Stinger missiles at the hapless helicopter.
Easy remedy: Make the armament attribute privateand specify public inheritance.
Inheritance Hierarchy Example: Symbolic Differentiation
Symbolic differentiation (taking the derivative of anexpression) can be accomplished with expressions trees.
E.g., the derivative of x*(x+4)-5 = 2x+4
-
*
+
5
X
X 4
An expressiontree for x*(x+4)-5
Rules for Symbolic Differentiation
d(A-B) = d(A) - d(B)
d(A+B) = d(A) + d(B)
d(A*B) = A*d(B) + d(A)*B
d(Constant) = 0
d(x) = 1
Basic Data Flow
Expression Trees
Differentiate
Simplify
However, there needs to be a wayto convert textual expressions to expressions trees, and vice versa.
Parsing
Parsing is the process of converting input expressionsinto expression trees.
It first must recognize the individual components:operators, variables, and constants (called tokens):
Equations Tokenizer Tokens
ExpressionTreee Builder
Expression Trees
Parser
Potential Data Classes
Input Stream
Token
Token Stream
Expression Tree
Expression Tree Node
Output Stream
Expression Tree Class
An expression tree suggests a natural hierarchy amongexpression tree nodes:
Node
OperatorNode
Leaf Node
BinaryOperator
UnaryOperator Constant Variable
Minus Add Sub Mult Div Exp
An "is-a"hierarchy
Inheritance and "Is-a" Hierarchies
Is-a hierarchies should be implemented through inheritance because:
Common properties can be factored out and defined only once (e.g. Printing)
New items can be added with minimal effort Rest of program can be written to operate on a generic
type Expr and ignore details of actual expressions The program documents itself by being organized to
mirror real-world objects