160 likes | 319 Views
Multiple Inheritance. CMPS 2143. Inheritance. Heart of concept of inheritance is the is-a relationship But in the real world, objects classified in multiple, mutually non-overlapping ways. spork is a fork and a spork is a spoon.
E N D
Multiple Inheritance CMPS 2143
Inheritance • Heart of concept of inheritance is the is-a relationship • But in the real world, objects classified in multiple, mutually non-overlapping ways. • spork is a fork and a spork is a spoon. • We could have a piece of furniture that is a table and a chair (chable?)
Multiple Inheritance • Combination of non-overlapping is-a relationships • Or maybe a variation of it as as-a relationships • A spork can be used as-a spoon and a spork can be used as-a fork • But there are problems (sigh, aren’t there always?)
Example: Smalltalk’s class Magnitude • Class Magnitude defines a protocol for objects that have measure – objects can be compared with one another • Number – supports arithmetic operations
Complex Number • A Complex Number is-a number and we can perform arithmetic operations on complex numbers • Want to inherit from Number, want to do mixed-mode arithmetic , eg. 4.5 + (3.1+23.3i) • Problem: comparison of two complex numbers • Complex numbers are not measurable
Inheritance Hiearchy • Need an inheritance Hierarchy where • Char is a subclass of Magnitude, but not Number • Integer should be a subclass of both • Complex should be a subclass of Number, but not of Magnitude
4 solutions • Make Complex a subclass of number, but redefine methods that compare to produce error messages • Flatten Inheritance Tree: Avoid inheritance altogether and redefine EVERY method in each of the classes Char, Integer, Complex, etc. • Use part of the inheritance hierarchy and simulate the rest • Just redefine all comparison operators • Make the two classes Magnitude and Number independent of each other and use multiple inheritance
Problems (sigh) • Inclusion of multiple inheritance causes 2 categories of problems • Name ambiguity (what if two classes inherited from each of a draw method?) • Problem is with child, so child must solve • Use fully qualified names One::draw(); vsTwo::draw(); • Rename/redefine/overload – BUT signatures will have to be different virtual int * draw () {One::draw();} virtual void draw(Graphics g) {Two::draw(g);}
Problems cont. • Impact on substitutability • Redefinition of the method name solves the problem locally • BUT NOT if we try to maintain a list of ONE of the parents • Example: GraphicalObject * g = new GraphicalCardDeck(); g->draw(); //will call draw method for CardDeck if //you redefined draw in GraphicalCardDeck //to call CardDeck::draw();
Solution to Problem 2 • Introduce new helper classes that inherit from the parents • Redefine the draw operation in each to use a method of a different name class CardDeckParent : public CardDeck { public: virtual void draw (cardDeckDraw();} virtual void cardDeckDraw() {CardDeck::draw();} };
Then redefine the two new methods in the child class class GraphicalCardDeck : CardDeckParent, GraphicalObjectParent{ public: virtual void cardDeckDraw() {..} virtual void goDraw() {…} };
GraphicalCardDeck *gcd = new GraphicalCardDeck(); CardDeck *cd = gcd; GraphicsObject *go = gcd; cd->draw(); //executes cardDeckDraw go->draw(); //executes goDraw gcd->draw(); //compiler error, ambiguous still
Multiple Inheritance of Interfaces • C++ and Smalltalk allow multiple inheritance of classes • Java and C# do not • Fake it with multiple inheritance of interfaces • REUSE concept, not code!
Study questions • Pg. 273: 1, 2, 4, 6