Presentation is loading. Please wait.

Presentation is loading. Please wait.

Generalization: Inheritance & Polymorphism

Similar presentations


Presentation on theme: "Generalization: Inheritance & Polymorphism"— Presentation transcript:

1 Generalization: Inheritance & Polymorphism
Chapter 6 Generalization: Inheritance & Polymorphism

2 Section 6.1: Progression of Roles

3 Generalization versus Abstraction
Frequently confused, but distinct Abstraction Simplify the description of something Generalization Find common properties in a set of abstractions

4 This chapter focuses on these first two.
Generalization “Identification, and possible organization, of common/shared properties of an abstraction” Hierarchy Polymorphism Genericity Patterns This chapter focuses on these first two.

5 Generalization: 4 Kinds
Hierarchy: Graph representing “is a” relationship Polymorphism (“many forms”): Loop to “iterate” through list works for arrays or linked list Genericity: “Parameterized” object: Sort object w/ type (int) parameter Patterns: Way to structure objects (e.g., client/server system)

6 Hierarchy Represented by generalize/specialize graph
Based on “is-a” relationship Is a form of knowledge representation Allows vocabulary for discussion Extendable without redefining everything Specialization can be added to proper subset of hierarchy

7 Hierarchy A generalization based on an “is-a” relation

8 Inheritance Terminology Important Dimensions Base class (superclass)
Derived class (subclass) Important Dimensions Programming: implement efficiently a set of related classes (mechanical) Design: organize coherently the concepts in an application domain (conceptual) Software Engineering: design for flexibility and extensibility in software systems (logical)

9 The Number Class Section 6.2: class Number { private: int value;
TextBox* textBox; public: Number(int initValue = 0); // start at initValue void ShowIn (TextBox& tbox); // place to display value void Show(); // display current value void Next(); // increment void Reset(); // get new value from user int Value(); // return current value ~Number(); }; Abstraction of an integer number that can be incremented

10 The Cycler Class class Cycler { Abstraction of a number that can be
private: int value; int base; TextBox* textBox; public: Cycler(int b = 10); // modulo base b void ShowIn (TextBox& tbox); // place to display value void Show(); // display current value void Next(); // increment void Reset(); // get new value from user int Value(); // return current value ~Cycler(); }; Abstraction of a number that can be incremented but is constrained to a range of 0 to base b.

11 Similarities Between the Number and Cycler Classes
Data: value : an internal integer value TextBox* : a pointer to a TextBox Code: ShowIn : provide TextBox where value is displayed Show : display current value in TextBox Reset : use TextBox to get new value from user Value : returns current internal value The Next() method is different!

12 Generalization-Specialization Hierarchy
Name: Counter Data: Code: Next Derived Class Name: Cycler Data: base Name: Displayable Number Data: value, TextBox* Code: ShowIn Show Reset Value Base Class

13 Generalization-Specialization Hierarchy
Name Shared Stuff Data Methods Name Data Methods

14 Logical Structure of a Cycler Object

15 Multiple Levels of Inheritance

16 An Inheritance Hierarchy of Displayable Numbers

17 Syntax of Inheritance Base Class Section 6.3:
class DisplayableNumber { public: DisplayableNumber(int init = 0); // initial value zero by default void ShowIn(TextBox& p); void Show(); void Reset(); int Value(); ~DisplayableNumber(); }; Base Class This is a complete class in and of itself and could have instances (objects) of it created.

18 Syntax of Inheritance (Continued)
class Number : public DisplayableNumber { public: Number(int init = 0); void Next(); ~Number(); }; Base Class Constructor Different, additional methods Derived Class Destructor

19 Syntax of Inheritance (Continued)
class Cycler : public DisplayableNumber { public: Cycler(int b, int init = 0); void Next(); ~Cycler(); }; Ditto info from previous slide public keyword Syntax Derived Class

20 Using Objects of Derived Classes
Number count(10); // initially 10 Cycler binary(2); // base 2 TextBox display(Location(10,10), Shape(50,50)); TextBox onoff (Location(20,20), Shape(50,50)); count.ShowIn(display); binary.ShowIn(onoff); count.Next(); // increment by 1 binary.Next(); // increment by 1 modulo 2 count.Show(); // display updated value binary.Show(); // display updated value int c = count.Value(); // get value of Number object int b = binary.Value(); // get value of Cycler object calling methods from base class methods specific to the class

21 Example of the Protected Section
class DisplayableNumber { private: TextBox* textBox; // place to display value protected: int value; // internal counter public: DisplayableNumber(int init); // initial value void ShowIn(TextBox& p); void Show(); void Reset(); int Value(); // reply current value ~DisplayableNumber(); }; private items are not accessible in derived classes protected items are accessible in derived classes anyone can see and manipulate public items

22 A Complete Derived Class
class Number : public DisplayableNumber { public: Number(int init = 0); void Next(); ~Number(); }; Number::Number(int init) : DisplayableNumber(init) { } void Number::Next() { value = value + 1; } Number::~Number() {} What order are the constructors done in? Use the base class’s constructor Not necessary if you just call the default (parameterless) constructor

23 A Complete Derived Class
class Cycler : public DisplayableNumber { private: int base; public: Cycler(int b, int init = 0); void Next(); ~Cycler(); }; Cycler::Cycler(int b, int init) : DisplayableNumber(init) { base = b; } void Cycler::Next() { value = (value + 1)%base; } Cycler::~Cycler() {} additional initialization not in base class can be done here “, base (b)”

24 Order of Constructor Execution
class Base { private: int value; public: Base(int init); }; class Derived : public Base { private: int base; public: Derived(int init, int b = 10); Base::Base(int init) { cout << "Base Constructor " << init << endl; } Derived::Derived(int b,int init):Base(init) { base = b; cout << "Derived Constructor " << b << endl; }

25 Order of Constructor Execution (cont’d)
void main(){ Derived derived(8, 20); } Result: Base Constructor 20 Derived Constructor 8

26 Circle Class class Circle { private: Location center; int radius;
Color drawColor; Canvas *canvas; public: Circle(); void DisplayIn(Canvas& can); void Draw(); void SetColor(Color color); void ChangeColor(); int Xvalue(); int Yvalue(); int GetRadius(); void Clear(Canvas& canvas); ~Circle(); };

27 MCircle Class class MCircle: public Circle { private:
Location direction; int resizespeed; int movespeed; public: MCircle(); void Resize(); void Move(); int GetResizeSpeed(); int SetResizeSpeed(); int GetMoveSpeed(); int SetMoveSpeed(); ~MCircle(); };

28 Circle Class Revisited
class Circle { private: Canvas *canvas; Color drawColor; protected: int radius; Location center; public: Circle(); void DisplayIn(Canvas& can); void Draw(); void SetColor(Color color); int Xvalue(); int Yvalue(); int GetRadius(); void Clear(Canvas& canvas); ~Circle(); }; Note that 2 variables moved from Private to Protected

29 Shape Base class? class Shape { private: Canvas *canvas; protected:
Color drawColor; Location center; public: Shape(); void DisplayIn(Canvas& can); void SetColor(Color color); int Xvalue(); int Yvalue(); void Clear(Canvas& canvas); ~Shape(); }; We can’t draw it; is it useful?

30 Replacing Inherited Methods
Section 6.4: Problem: You have a base class. You’re writing a derived class. You don’t like a method in base class! You want to redefine method. Example: DisplayableNumber::Reset() reads text box; you want to reset to initial value!

31 Solution: Redefine Base Method
In derived class, we must: Remember initial value to base class Re-define “Reset()” method Try writing derived class “RestartCounter” now!

32 Here’s what we want... Implement this! Name: Displayable Name: Counter
Number Data: int value, TextBox* Code: ShowIn Show Value Reset() Name: Counter Data: Code: Next Name: Restart Counter Data: int original Code: Reset() Implement this!

33 Review... class DisplayableNumber {
private: TextBox* textBox; // place to display value protected: int value; // internal counter public: DisplayableNumber(int init); // initial value void ShowIn(TextBox& p); void Show(); void Reset(); // value = number in textBox int Value(); // reply current value }; class Number : public DisplayableNumber { Number(int init = 0); void Next();

34 Solution class RestartCounter : public Number { private: int original;
RestartCounter(int init=0); void Reset() {value=original;} } RestartCounter::RestartCounter(int init) : Number(init) {original=init;}

35 Invocation of Method is “Looked up” through layers

36 Extending Inherited Methods
Section 6.5: Problem: You have a base class. You’re writing a derived class. A method in base class is not quit ok. You want to extend method. Example: Base Reset() reads text box; in class Cycler you want to insure number’s smaller than base! Last time: redefine

37 Modify Cycler to Extend Reset()
class DisplayableNumber { private: TextBox* textBox; // place to display value protected: int value; // internal counter public: DisplayableNumber(int init); void ShowIn(TextBox& p); void Show(); void Reset(); // value = number in textBox int Value(); // reply current value }; class Cycler : public DisplayableNumber { private: int base; public: Cycler(int base, int init = 0); void Next(); void Reset() { } Fill this in!

38 Modify Cycler to Extend Reset()
class DisplayableNumber { private: TextBox* textBox; // place to display value protected: int value; // internal counter public: DisplayableNumber(int init); void Reset(); // value = number in textBox }; class Cycler : public DisplayableNumber { private: int base; public: Cycler(int base, int init = 0); void Next(); void Reset() { DisplayableNumber::Reset(); value = value % base; } Surprise!

39 Morale of the Story Derived class can re-use method name from base class This replaces base method But derived class can also call base method, to extend base method.

40 Hiding Inherited Methods
Section 6.6: Let’s talk about a very serious problem. Sometimes a base method doesn’t make sense to a derived class. What do we do?

41 Example class Rectangle { public: void SetShape(Shape s); }
class Square : public Rectangle { // inherits SetShape You can reshape square into rectangle! Oh no!

42 Solutions 1. Override base method so it’s harmless
2. Use private inheritance so base method isn’t visible 3. Revise the inheritance hierarchy Let’s look at all three...

43 Solution 1a: Override base method
void Square::SetShape(Shape shape){} List pros and cons for this solution! Pro: user can no longer turn square into rectangle Con: user cannot change length of sides of a rectangle (but you could use new method to do that).

44 Solution 1b: Override base method
void Square::SetShape(Shape shape) { Rectangle::SetShape( Shape(shape.Width(), shape.Width()) ) } List pros and cons for this solution! Pro: user can no longer turn square into rectangle Con: user may spend all day debugging code not realizing that Square hard-wires rectangle height to width.

45 Solution 2: Use private inheritance
class Square : public Rectangle {…} What’s the effect of deleting “public”? What goes in the “…”? List pros and cons for this solution! What does public, protected, private, or “nothing” mean here? Pro: user can no longer turn square into rectangle Con: You have more work: You must explicitly list each method of Rectangle in Square

46 Solution 2: What goes in “…”
class Square : public Rectangle { public: Square(int side); void SetSide(int side); Rectangle::SetLocation; Rectangle::Draw; Rectangle::Clear; Rectangle::Rotate; } Write bodies of Constructor & SetSide Pro: user can no longer turn square into rectangle Con: You have more work: You must explicitly list each method of Rectangle in Square Surprise!

47 Bodies of Constructor & SetSide
Square::Square(int side) : Rectangle(Shape(side,side)) {} void Square::SetSide(int Side) { SetSide(Shape(side,side)); }

48 Solution 3: Revise Inheritance Hierarchy
Try writing class definitions for this… Be sure you solve the SetSize problem! ??? Square Rectangle Pro: user can no longer turn square into rectangle Con: You have more work: You must explicitly list each method of Rectangle in Square

49 SetLocation Draw Clear Rotate
Answer... Quadrilateral SetLocation Draw Clear Rotate Square SetSide Rectangle SetShape Note error in book’s diagram

50 Steps to Unlocking the Power of Inheritance
Pure Virtual Methods Virtual Methods Type Casting

51 This syntax cannot be used with pointers.
Type Casting Allows flexible structures to be built Idea: Treat a derived class object as if it were a base class object Syntax: BaseClassName (derivedClassObject) or (BaseClassName) derivedClassObject This syntax cannot be used with pointers.

52 Type Casting DisplayableNumber* ShowIn Show Value Next Number*

53 Type Casting Using Pointers to an Object
TextBox display(Location(100,100), Shape(75, 50)); Number* number = new Number(100); DisplayableNumber* dnp; Number->Next(); dnp = (DisplayableNumber*) number; dnp->ShowIn(display); dnp->Show(); Type Cast We may only call methods from DisplayableNumber on dnp, even though it’s really an object of type Number!

54 Type Casting Using References
TextBox display(Location(100,100), Shape(75, 50)); Number number(100); number.Next(); DisplayableNumber& displayable = (DisplayableNumber&) number; displayable.ShowIn(display); displayable.Show();

55 Type Casting Errors Wrong! DisplayableNumber* numPtr;
Number *count1 = new Number(100); Number count2(200); numPtr = (DisplayableNumber*) count1; DisplayableNumber& numRef = (DisplayableNumber)count2 numPtr->Next(); numRef.Next(); Wrong! DisplayableNumber doesn’t have a Next() method!

56 Why Type Casting? Allows us to treat a collection of objects uniformly by viewing them as their base class. Example 1 : Shapes from Project 1 Example 2 : NumberPanel class example

57 Shapes from Project 1 Derive Circle and Rectangle from “Shape”
avoid code duplication ShapeManager handles instances of Shape E.g.: Shape SetLocation GetBounds ... Location loc Rectangle bounds GameCircle SetCenter SetRadius Draw GameRectangle SetSize

58 Type Casting to Create a Polymorphic Structure
class NumberPanel { private: DisplayableNumber *number[3]; // array for simplicity int last; Panel *panel; public: NumberPanel(); void Add( DisplayableNumber* num ); // add num void ShowIn(Panel & panel); // put all objects here void Show(); // Show all objects in panel };

59 Implementation of the NumberPanel Class
NumberPanel::NumberPanel() { last = -1; panel = (Panel *)0; } void NumberPanel::Add( DisplayableNumber* num) { if ( last < 2 ) { number[++last] = num; TextBox* tbox = new TextBox(Location(last*60,20) Shape(50,20)); num->ShowIn(*tbox); if (panel) panel->Add(*tbox);

60 Implementation of NumberPanel Class (Cont.)
void NumberPanel::ShowIn( Panel& panel) { this->panel = &panel;} void NumberPanel::Show() { if (last > -1 ) for(int i = 0; i <= last; i++) number[i]->Show(); } NumberPanel::~NumberPanel() {}

61 Example of NumberPanel Flexibility
Frame display(Location(100,100), Shape(200,200)); Panel panel(display, Location(10,10), Shape(180,40)); NumberPanel numberPanel; Number number(100); Cycler octal(8); JumpCounter length(0); numberPanel.ShowIn(panel); // add different kinds of counters to the panel numberPanel.Add((DisplayableNumber*)&number); numberPanel.Add((DisplayableNumber*)&cycler); numberPanel.Add((DisplayableNumber*)&octal);

62 Example of NumberPanel Flexibility (Continued)
// manipulate individual counter objects number.Next(); octal.Next(); length.Next(50); // display all of the new values numberPanel.Show();

63 Implicit vs. Explicit Type Casting
Number *number; DisplayableNumber *displayable =(DisplayableNumber*)number Implicit DisplayableNumber *displayable = number; Avoid implicit typecasting. Say what you mean in your code!

64 Implicit vs. Explicit Type Casting In Parameter Passing
Given the following method: NumberPanel::Add(DisplayableNumber * dn); Call with Explicit Type Cast NumberPanel panel; Number *n = new Number(100); panel.Add((DisplayableNumber*)n); Call with Implicit Type Cast Number *c = new Number(100); panel.Add(c); Other developers may not realize that Add takes a DisplayableNumber

65 Widening vs. Narrowing Widening Narrowing
Type casting from a derived class to a base class. Always Safe! Can be checked by the compiler. Narrowing Type casting from a base class to a derived class. Safety depends on the programmer.

66 Widening/Narrowing Example
DisplayableNumber *DNptr; Number *number = new Number(100); Cycler *cycler; DNptr = (DisplayableNumber*)number; // safe; it widens cycler = (Cycler*)DNptr; // oops! cycler->Next(); // who knows what this will do!

67 Interface Sharing Suppose
Section 6.8 Interface Sharing Suppose Shape SetLocation GetBounds Draw ... Location loc Rectangle bounds GameCircle SetCenter SetRadius GameRectangle SetSize Shape::Draw() is called. This can be a problem, because the object is actually a circle and Shape::Draw does not implement drawing a circle. In fact, there is no general way to implement drawing in the Shape base class. Virtual functions give us a way to handle this GameCircle * circ = new GameCircle(Location(100,100)); Shape * shape = (Shape*)circ; shape.Draw(); // which Draw() is called?

68 Revised Clock Class: Interface Sharing Example
Section 6.8 Revised Clock Class: Interface Sharing Example class Clock { private: Number* number; // Connect(ed)To a Number Cycler* cycler; // Connect(ed)To a Cycler ... public: ConnectTo(Number& cnt); ConnectTo(Cycler& cnt); };

69 Revised Clock Class: (Continued)
void Clock::ConnectTo(Number& cnt) { number = &cnt;}; void Clock::ConnectTo(Cycler& cnt) { cycler = &cnt;}; void Clock::Notify() { if (number) number->Next(); else if (cycler) cycler->Next(); }

70 Repetitive Code in the Clock Class
class Clock { private: Number* number; //Connect(ed)To a Counter Cycler* cycler; //Connect(ed)To a Cycler BiCycler* biCycler; //Connect(ed)To a BiCycler UpCounter* upCounter; //Connect(ed)To a UpCounter DownCounter* downCounter; //Connect(ed)To a DownCounter BatchCounter* batchCounter; //Connect(ed)To a BatchCounter JumpCounter* jumpCounter; //Connect(ed)To a JumpCounter SwitchCounter* switchCounter;//Connect(ed)To a SwitchCounter ... YUCK! We need a better way!

71 Declaring a Virtual Method
class DisplayableNumber { private: ... public: virtual void Next(); // virtual Next method }; // in implementation file void DisplayableNumber::Next() {} //default definition

72 Redefining the Clock Class
class Clock { private: DisplayableNumber *number; // only refer to base class public: ... void ConnectTo(DisplayableNumber* dn); void ConnectTo(DisplayableNumber& dn); void Notify(); };

73 Redefining the Clock Class (Continued)
// in implementation file void Clock::ConnectTo (DisplayableNumber* dn) { number = dn; } void Clock::ConnectTo (DisplayableNumber& dn) { number = &dn; } void Clock::Notify() { number->Next(); // invokes derived class method number->Show(); // invokes base class method }

74 Using the Revised Clock Class
Clock oneMinute(60*1000), oneSecond(1000); Number minutes(0); Cycler seconds(60); oneMinute.ConnectTo( (DisplayableNumber&) minutes); oneSecond.ConnectTo( (DisplayableNumber&) seconds); oneMinute.Start(); oneSecond.Start();

75 Example of Run-Time Binding
class Clock { private: DisplayableNumber *number; // only refer to base class public: void Notify(); }; void Clock::Notify() { number->Next(); // invokes derived class method ... } Binding of Next() in Notify() is done at compile-time by an invisible pointer since actual type isn’t known until execution!

76 Binding Selection of code for a function invocation
Static, compile time efficient Dynamic, run time flexible default in many o-o languages Java, Smalltalk Must be explicitly programmed in C++

77 Pure Virtual Methods Definition of “Abstract” Base Class ... public:
class AbstractDisplayableNumber { ... public: virtual void Next() = 0; // pure virtual method }; Definition of a “Concrete” Derived Class class ConcreteCounter : public AbstractDisplayableNumber { void ConcreteCounter::Next() {...some implementation ... }

78 Examples of Using Abstract Classes
AbstractDisplayableNumber *adn; // ok - pointer to abstract // class ConcreteCounter*cc; // ok - pointer to concrete class // NO! - class is abstract AbstractDisplayableNumber n(100); ConcreteCounter c(100); // ok - instance of concrete class cc = &c; // ok - types are the same adn = &c; // ok and->Next(); // ok

79 Class Structure for Polymorphism

80 Typical Component Class Hierarchy

81 Example from Project 1 No default Draw() for Shape class
Want ShapeManager to call Draw() on its Shape objects. What do we do?

82 Use of Polymorphism: Component Example
class ComponentManager { private: Component *member[10]; int number; ... public: ComponentManager() : number(0) {} void Add(Component *cmp) { member[number++] = cmp; } Component* Inside(int x, int y) {for(int next = 0; next<number; next++) if (member[next]->inside(x,y) ) return member[next]; return NULL; } };

83 What happens if I don’t get the base class right the first time?
Name: Displayable Number Data: value, TextBox* Code: ShowIn Show Reset Value Base Class Name: OctalNumber Data: Code: Next Derived Class

84 Solution: Override the base class method Show
Problem Problem: The representation of the octal number in the TextBox should appear in an octal number representation: preceded by a zero and without the digits 8 or 9. Solution: Override the base class method Show Implication: The TextBox variable must be moved to the protected section Design decisions revealed: The DisplayableNumber’s value is displayed in a TextBox, The TextBox is accessed via a pointer, The name of the pointer is textBox, and The TextBox has a SetText method.

85 Solution Solution: Factor the base class to separate: Formatting the character string to be displayed, and Displaying the string in the TextBox.

86 Refactoring the DisplayableNumber Class
class DisplayableNumber { private: TextBox* textBox; protected: int value; virtual char* Format(); // produce string to display virtual int Parse(char* input); // convert user // input to value public: DisplayableNumber(int initValue = 0); void ShowIn(TextBox& p); void Show(); void Reset(); ~DisplayableNumber(); };

87 Refactoring the DisplayableNumber Class
char* DisplayableNumber::Format() { char* asString = new char[10]; ostrstream format(asString); format << value; // use decimal formatting return asString; } void DisplayableNumber::Show() { if (textBox) textBox->SetText(Format());

88 Refactoring the DisplayableNumber Class
int DisplayableNumber::Parse(char* input) { int decimalValue; istrstream format(input); format >> decimalValue; // use decimal formatting return decimalValue; } void DisplayableNumber::Reset() { if (textBox) value = Parse(textBox->GetText());

89 Defining the Octal Number Class
class OctalNumber : public Number { protected: char* Format(); // how to print an octal // number int Parse(char* input) // how to read an octal public: OctalNumber(int init); ~OctalNumber(); };

90 Defining the Octal Number Class
OctalNumber::OctalNumber (int init) : Number(init) {} char* OctalNumber::Format() { char* asString = new char[10]; ostrstream format(asString); format << oct << value; // format value as octal return asString; } int OctalNumber::Parse(char* input) { int octalValue; istream is(input); is.flags(ios::oct); // set stream to read as octal is >> octalValue; return octalValue; OctalNumber::~OctalNumber() {}

91 Multiple Inheritance Inherit from more than one base class
Sometimes useful multiple code reuse flexible polymorphism Not supported in all O-O languages E.g., Java multiple interface inheritance (flexible polymorphism) single code inheritance (limited code reuse)

92 Simple “Mixin” Class class Named { private: char* name; public:
Named(char* originalName); int IsNamed(char* possibleName); char* GetName(); void SetName(char* newName); ~Named(); };

93 Both superclasses are constructed
Multiple Inheritance Inheriting multiple “orthogonal” classes class NamedNumber : public Number, public Named { public: NamedNumber(int initialValue, char* name); ~NamedNumber(); }; // implementation NamedNumber::NamedNumber(int intialValue, char* name) : Number(initialValue), Named(name) {} Both superclasses are constructed

94 Using NamedNumber Inherited from Number Inherited from Named
NamedNumber time(0, "Elapsed Time"); //... time.Next(); if (time.IsNamed("Elapsed Time") ) cout << time.GetName() << " is ” << time.Value() << endl; Inherited from Number Inherited from Named Inherited from Named Inherited from Number

95 Improving Polymorphism in Clock
class AbstractDisplayableNumber { //... public: virtual void Next() = 0; void Show(); }; Clock cannot be used for classes other than AbstractDisplayableNumber class Clock { private: AbstractDisplayableNumber *number; public: void ConnectTo(AbstractDisplayableNumber * dn); void ConnectTo(AbstractDisplayableNumber & dn); void Notify(); };

96 Animation Class Next() and Show() are similar to
class Animation { public: Animation(...); // ... void Next(); // generate the next image in the // animation sequence; make this the // current image to be shown void Show(); // present the current image //... }; Next() and Show() are similar to AbstractDisplayableNumber methods.

97 Pure Abstract “Mixin” Class
Define an “interface” for common methods Interface: a class with no data or code class Sequenced // pure abstract class { public: virtual void Next() = 0; // compute the next // element in the sequence virtual void Show() = 0; // present the current };

98 More General Clock Clock uses Sequenced interface class Clock {
private: Sequenced *sequence; public: void ConnectTo(Sequenced * seq); void ConnectTo(Sequenced & seq); void Notify(); }; void Clock::ConnectTo (Sequenced * seq) {sequence = seq;} void Clock::ConnectTo (Sequenced & seq) {sequence = & seq;} void Clock::Notify() { sequence->Next(); sequence->Show(); }

99 Using Sequenced with DisplayableNumber Hierarchy
DisplayableNumber could inherit from Sequenced class DisplayableNumber: public Sequenced Subclasses of DisplayableNumber could inherit Sequenced class Cycler: public DisplayableNumber, public Sequenced New subclasses of DisplayableNumber subclasses could mix in Sequenced class TimedCycler: public Cycler, public Sequenced

100 Multiple Inheritance with Abstract Class
class TimedNumber : public Number, public Sequenced { public: TimedNumber(int initialValue); }; class TimedAnimation : public Animation, public Sequenced { TimedAnimation(...);

101 Using TimedNumber and TimedAnimation
Clock slowTimer("Slow", 1000); Clock fastTimer("Fast", 50); //... TimedNumber count(0); TimedAnimation *movie = new TimedAnimation(...); slowTimer.ConnectTo( (Sequenced&)count ); fastTimer.ConnectTo( (Sequenced*)movie ); Are these explicit casts required? No Are these explicit casts required?

102 Resolving Name Ambiguity in Multiple Inheritence
What if same member is in superclasses? Aclass void DoSomething(); Bclass void DoSomething(); Cclass Cclass cObj; cObj.DoSomething(); cObj.Bclass::DoSomething(); Ambiguous. Compiler error Disambiguate with scope resolution operator ‘::’


Download ppt "Generalization: Inheritance & Polymorphism"

Similar presentations


Ads by Google