390 likes | 831 Views
L4: Multiple Inheritance. Introduction Problems of Single Inheritance and solutions Problems of Multiple Inheritance: Name ambiguity Substitutability Common ancestors 5 Solutions to the Problems Virtual Inheritance Inner Classes Chapter 13 of Budd. Multiple Inheritance.
E N D
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism L4: Multiple Inheritance • Introduction • Problems of Single Inheritance and solutions • Problems of Multiple Inheritance: • Name ambiguity • Substitutability • Common ancestors • 5 Solutions to the Problems • Virtual Inheritance • Inner Classes • Chapter 13 of Budd
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Multiple Inheritance • Where a child class can inherit from more than one parent class directly • Supported in C++, Eiffel • Not supported in Java, C#
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism A Quote Multiple inheritance allows several objects to act as base objects ... The characteristics of several different object classes can be combined to make up a new object. For example, say we have an object class CAR and an object class PERSON. We could use both of these to define a new object class CAR-OWNER … Sommerville, “Software Engineering”, 4th Edition
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Problem of Single Inheritance • We can divide the world into an infinite number of hierarchies • For complex problems strict hierarchies almost always end up with trade-offs and ambiguities.
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Example Object Ordered Number Char Complex? Fraction Float Integer
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Solutions • Make Complex a subclass of Number and override Ordered methods • Avoid inheritance, and redefine all methods • Use a partial inheritance hierarchy • Use multiple inheritance
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Problems of Multiple Inheritance • Name ambiguity • Substitutability • Common ancestors
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism GraphicalObject draw() CardDeck draw() GraphicalCardDeck Name Ambiguity • The same name can mean different things to different ancestors
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Solution A • Explicit disambiguation: GraphicalCardDeck gcd; gcd.CardDeck::draw(); gcd.GraphicalObject::draw();
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Solution B • With different type signatures, can use straight overloading: class GCD : public CardDeck, public GO { public: virtual Card *draw(){ return CardDeck::draw();}; virtual void draw(GraphicsContext &g){ GraphicalObject::draw(g);}; };
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Solution B2 class GCD : public CardDeck, public GO { public: using CardDeck::draw; using GraphicalObject::draw; };
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Solution C • With the same type signatures, we're in trouble: class GCD: public CardDeck, public GO { public: virtual void draw(){ return CardDeck::draw();} virtual void paint(){GO::draw();}; }; GraphicalObject *g = new GraphicalCardDeck(); g->draw();
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Solution D class CardDeckParent : public CardDeck { virtual void draw() {cardDeckdraw();}; virtual void cardDeckDraw(){CardDeck::draw();}; }; class GraphicalObjectParent: public GO { virtual void draw() {goDraw();}; virtual void goDraw(){GO::draw();}; }; class GraphicalCardDeck:public CDP,public GOP { virtual void cardDeckDraw() {CDP::cardDeckDraw();}; virtual void goDraw() {GOP::goDraw();}; };
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Solution D GraphicalCardDeck *gcd = new GCD(); CardDeck *cd = dynamic_cast<CardDeck*>(gcd); GraphicalObject *go = dynamic_cast<GraphicalObject*>(gcd); cd->draw(); // ok go->draw(); // ok gcd->cardDeckDraw(); // ok gcd->goDraw(); // ok gcd->draw(); // error - ambiguous
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Common Ancestors • The “diamond of death”: A A A B C B C D D
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Stream InStream OutStream InOutStream C++ Example InStream and OutStream inherit and override a method in Stream. InOutStream inherits the same method.
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Virtual Inheritance class Stream {...}; class InStream: public virtual Stream {...}; class OutStream: public virtual Stream {...}; class InOutStream: public InStream, public OutStream {...}; • The ambiguity occurs in InOutStream, and the solution involves the definitions of InStream and OutStream.
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Inner Classes • In languages which allow inner classes (Java, C#), we can simulate multiple inheritance after a fashion:
SFDV4001 / OOP with C++ / Lecture 4 / Polymorphism Java Inner Classes class GraphicalCardDeck extends CardDeck { public void draw() { // draw a card from a deck} private class DrawingClass extends GraphicalObject { public void draw() {// draw a card on screen} } private DrawingClass drawer = new DrawingClass; public GraphicalObject myDrawingObject(){ return drawer;}; }