Introduction to Object Oriented Programming, 3rd Ed

Timothy A. Budd

Chapter 13

Multiple Inheritance

Outline

  1. Roadmap
  2. Inheritance as Categorization
  3. Inheritance as Combination
  4. An Example -- Complex Numbers
    1. Possible Solutions
    2. Numbers as Combinations
  5. Another Example -- Walking Menus
  6. Problem with MI - Name Ambiguity
    1. One Solution: Redefinition
    2. Problem with Redefinition Solution
    3. Other Approaches to Name Ambiguity
  7. Multiple Inheritance of Interfaces
  8. Inheritance from Common Ancestors
    1. Data Field in Common Ancestor
  9. Inner Classes
  10. Chapter Summary

Other Material

Intro OOP, Chapter 13, Outline

Roadmap

In this chapter we will investigate some of the problems that can arize when a language allows a child class to have multiple parents.
Intro OOP, Chapter 13, Slide 01

Inheritance as Categorization

In one sense, the process of inheritance is a form of categorization.
A TextWindow is a type of Window, so class TextWindow inherits from class Window.

But in the real world, most objects can be categorized in a variety of ways. The author of the textbook is

None of these are proper subsets of the other, and we cannot make a single rooted inheritance hierarchy out of them.
Intro OOP, Chapter 13, Slide 02

Inheritance as Combination

Instead, real world objects are combinations of features from different classification schemes, each category giving some new insight into the whole: Note that we have not lost the is-a relationship; it still applies in each case.
Intro OOP, Chapter 13, Slide 03

CS Example - Complex Numbers

Two abstract classifications

Three specific classes

Intro OOP, Chapter 13, Slide 04

Possible Solutions

1.
Make Number subclass of Magnitude, but redefine comparison operators in class complex to give error message if used. (subclassing for limitation)

2.
Don't use inheritance at all - redefine all operators in all classes. (flattening the inheritance tree).

3.
Use part inheritance, but simulate others - use Number, but have each number implement all relational operators.

4.
Make Number and Magnitude independent, and have Integer inherit from both. (multiple inheritance).
Intro OOP, Chapter 13, Slide 05

Inheritance as a form of Combination

Intro OOP, Chapter 13, Slide 06

Another Example - Walking Menus

Intro OOP, Chapter 13, Slide 07

Problem with MI - Name Ambiguity

What happens when same name is used in both parent classes.

Intro OOP, Chapter 13, Slide 08

One Solution: Redefinition

One solution is to redefine one or the other operation in the child class.
class GraphicalCardDeck : public CardDeck, public GraphicalObject {
public:
	virtual void draw () { return CardDeck::draw(); } 
	virtual void paint () { GraphicalObject::draw(); }
}

	GraphicalCardDeck gcd;
	gcd->draw(); // selects CardDeck draw
	gcd->paint(); // selects GraphicalObject draw
Intro OOP, Chapter 13, Slide 09

Problem with Redefinition Solution

The redefinition solution is not without cost, however.

Now what happens when we run up against the principle of substitution?


	GraphicalObject * g = new GraphicalCardDeck();
	g->draw(); // opps, doing wrong method!

This problem can be mitigated, but the solution is complex and not perfect.
Intro OOP, Chapter 13, Slide 10

Other Approaches to Name Ambiguity

Other languages use different approaches to solving the problem of ambiguous names
Intro OOP, Chapter 13, Slide 11

Multiple Inheritance of Interfaces

Multiple inheritance of interfaces does not present the same problem of name ambiguity as does multiple inheritance of classes. This is why Java permits multiple inheritance of interfaces, not of classes.

Nevertheless, C# does not permit the same method name to be inherited from two parent interfaces.

Intro OOP, Chapter 13, Slide 12

Inheritance from Common Ancestors

Another problem with MI occurs when parent classes have a common root ancestor. Does the new object have one or two instances of the ancestor?

Intro OOP, Chapter 13, Slide 13

Data Field in Common Ancestor

Imagine that the common ancestor declares a data member. Should the child class have one copy of this data field, or two?

Both answers can be justified with examples.

C++ gets around this by introducing the idea of a virtual parent class. If your parent is virtual there is one copy, and if not there is two.

Not a perfect solution, and makes the language complicated.

Intro OOP, Chapter 13, Slide 14

Inner Classes

The ability to next classes in C++ and Java provides a mechanism that is nearly equivalent to multiple inheritance, without the semantic problems.
class Child extends ParentOne {
	...
	class InnerChild extends ParentTwo {
		...
		// can access both parents
	}
}
Within the inner class you can access methods from both parent classes. This idiom is used a lot in Java. Solves many problems that would otherwise be addressed using MI. Not exactly equivalent to MI, but very close.
Intro OOP, Chapter 13, Slide 15

Chapter Summary

In this chapter we have explored some of the problems that arise of the concept of multiple inheritance.
Intro OOP, Chapter 13, Slide 16