ObjectOriented Design and Inheritance The Big Picture 1
Object-Oriented Design and Inheritance The Big Picture 1
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: • Simplifies programming • Allows code to be reused through sharing • Can refine and extend code through virtual methods. 2
Example: Stacks and Queues Rear Front Items exit here Items enter here Items both enter and exit here Top 3
Stack as a Variation of Queue Front Items exit here Rear Items enter here Items exit Front here Items enter here 4
Data Structures Terminology l l 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 – l First-in, First-out (FIFO) We will call a stack a front queue since items enter front – Last-in, First-out (LIFO) 5
Generalization Class Diagram We will say that front queues and rear queues are extensions (derived subclasses) of a general queue class: Queue Front. Queue Rear. Queue 6
Attributes (Data) in Common l What attributes do stacks (front queues) and queues (rear queues) have in common? – – – An underlying structure (for example, an array or linked list) A place where items are added (for example, an index) A place from which items are removed 7
Operations in Common l 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 8
Generalization Diagram Again Queue max. Size: Integer front: Integer rear: Integer 1 Item * items display(): void add(Item): void remove(): Item empty(): Boolean full(): Boolean Front. Queue Rear. Queue 9
Abstract Classes l The Queue class is conceived to be what is common to both the Front. Queue and Rear. Queue classes l It makes no sense to make an object of type Queue; it is abstract (name in italics) l Operations in italics are abstract, like place holders; they must be overridden by the extending classes Front. Queue and Rear. Queue The Front. Queue and Rear. Queue classes inherit data attributes from Queue l 10
Polymorphism is the ability of a language to determine which 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 among operations of the same name dynamically at run time. In C++, pure polymorphism is achieved through inheritance and virtual functions. 11
An Abstract Queue. Info Class in C++ class Queue. Info { protected: Item. Array items; Integer max. Size; Integer front; Integer rear; public: Queue. Info(Integer size); ~Queue. Info(); void add(Item. Array new. Items, Integer num. Items); virtual void display(); virtual void add(Item item) =0 ; virtual Item remove() =0 ; virtual Boolean empty() =0 ; virtual Boolean full() =0 ; }; 12
Notes on the Queue. Info Class l l l 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) 13
Notes on the Queue. Info Class (cont'd) The Queue. Info constructor is not virtual, and will be shared by Rear. Queue. Info and Front. Queue. Info objects l • Must be implemented by Queue. Info class The add method is overloaded: • • • The non-virtual version will be shared and must be implemented by Queue. Info class The virtual version must have separate definitions in both Rear. Queue. Info and Front. Queue. Info classes 14
The Difference Between Overloading and Overriding Suppose q is of type Front. Queue. Consider: l § § l l l q->add(item. Array, num. Items); 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 15
The Difference Between Overloading and Overriding (cont'd) Suppose q is of declared type Queue. Consider: l § l l q->add(item); Since the one-parameter add method is only defined for Front. Queues and Rear. Queues, 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 16
Pure Polymorphism Example class Command. Interpreter. Info { private: Queue q; // either a Rear. Queue or Front. Queue Character cmd; // queue command: c, a, r, or d Character qtype; // queue type: r or f Integer qsize; // queue size. . . public: Command. Interpreter. Info(); void execute(); // run this command interpreter private: . . . void process. Create(); // process a cr or cf command void check. EOF(); // check for premature EOF. . . }; 17
Pure Polymorphism Example (cont'd) void Command. Interpreter. Info: : process. Create() { if (cmd != 'c') { <error: first command must be create> } cin >> qtype; check. EOF(); if ( (qtype == 'f') || (qtype == 'r') || (qtype == 'p') ) { cin >> qsize; check. EOF(); switch ( qtype ) { case 'f': q = new Front. Queue. Info(qsize); cout << "Front"; break; case 'r': q = new Rear. Queue. Info(qsize+1); cout << "Rear"; break; case 'p': . . . } cout << " Queue Created of Size " << qsize << endl; } else { <error: bad queue type> } } 18
Queue. Info Constructor l l Queue. Info objects are not explicitly constructed using new However, a Queue. Info constructor can be defined as what is common between Front. Queue. Info and Rear. Queue. Info: : Queue. Info(Integer size) { max. Size = size; items = new Item[max. Size]; for (Integer i = 0; i < max. Size; i++) { items[i] = NULL; } } 19
Defining Subclasses in C++: Example class Front. Queue. Info : public Queue. Info { public: Front. Queue. Info(Integer n); void add(Item item); Item remove(); Boolean empty(); Boolean full(); void display(); }; Similarly for Rear. Queue. Info 20
Notes on the Example l l l The “: public Queue. Info” construction means that Front. Queue. Info is to inherit all public and protected methods from Queue. Info Front. Queue. Info has its own constructor to supplement that “inherited” from Queue. Info Front. Queue. Info has a display method, even though it doesn't have to use it. 21
Subclass Constructors for subclasses indicate in their headers which parent class constructor to use: Front. Queue. Info: : Front. Queue. Info(Integer n): Queue. Info(n) { < code to initialize a new front queue > } Rear. Queue. Info: : Rear. Queue. Info(Integer n): Queue. Info(n) { < code to initialize a new rear queue > } 22
Non-Pure Virtual Methods l l The display method in the Queue. Info class is virtual, but not pure Thus, it has a definition in the Queue. Info class: void Queue. Info: : display() { for (Integer i = 0; i < max. Size; i++) { if ( items[i] == NULL ) cout << " ___" ; else items[i]->display(); } cout << endl; } 23
Non-Pure Virtual Methods (cont'd) l l 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 24
Inheritance and Separate Compilation When a subclass and its parent class are in separate modules, the subclass module must be remade whenever the parent class module is. Makefile: Rear. Queue. Info. o: Queue. Info. o Rear. Queue. Info. cc. . . <TAB>g++ -c Rear. Queue. Info. cc -o Rear. Queue. Info. o Failure to do this can cause bizarre behavior. 25
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 Phoenixherds of kangaroos (since disturbed animals might well give away a helicopter's position). The head of the Defense Science & Technology Organization's Land Operations/Simulation division reportedly instructed developers to model the local marsupials’ movements and reactions to helicopters. 26
Inheritance Pitfalls (cont'd) Being efficient programmers, they just re-appropriated some code originally used to model infantry detachment reactions under the same stimuli, changed the mapped icon from a soldier to a kangaroo, and increased the figures’ speed of movement. Enemy. Infantry position type speed armament . . . Kangaroo 27
Inheritance Pitfalls (cont'd) Eager to demonstrate their flying skills for some visiting American pilots, the hotshot Aussies “buzzed” the virtual kangaroos in low flight 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 private and specify public inheritance. 28
A Better Design Desert. Object position type speed . . . Enemy. Infantry Kangaroo armament 29
Inheritance Hierarchy Example: Symbolic Differentiation Symbolic differentiation (taking the derivative of an expression) can be accomplished with expressions trees. E. g. , the derivative of x*(x+4)-5 = 2 x+4 5 * An expression tree for x*(x+4)-5 + X X 4 30
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 31
Transforming the Expression Tree - 5 * Apply derivation rules * + X X 0 + 4 * 1 + X 1 0 + X 4 32
Simplifying the Expression Tree - * 1 1 0 + X * + X Apply simplification rules 0 + + X 4 4 33
Basic Data Flow Differentiate Expression Trees Simplify However, there needs to be a way to convert textual expressions to expressions trees, and vice versa. 34
Parsing is the process of converting input expressions into expression trees. It first must recognize the individual components: operators, variables, and constants (called tokens): Equations Parser Tokenizer Tokens Expression Treee Builder 35
Total Data Flow Equations Parser Differentiate Expression Trees Simplify Output Unparser 36
Potential Data Classes l l l Input Stream Token Stream Expression Tree Node Output Stream 37
Potential Algorithm Classes l l l Main Parser Differentiator Simplifier Unparser 38
Expression Tree Class An expression tree suggests a natural hierarchy among expression tree nodes: An "is-a" hierarchy Node Operator Node Unary Operator Minus Leaf Node Binary Operator Add Sub Variable Constant Mult Div Exp 39
Inheritance and "Is-a" Hierarchies Is-a hierarchies should be implemented through inheritance because: l • • 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 40
Deep vs. Shallow Hierarchies A deep hierarchy: A shallow hierarchy: A deep hierarchy yields more opportunity for reuse, but it may be difficult to follow code. A shallow hierarchy indicates objects do not have much commonality. A good design will balance depth and breadth. 41
Some things to consider in terms of OOD and Inheritance End of Lecture 42
- Slides: 42