multiple inheritance - bguoosd132/wiki.files/lecture10.pdf · a common analogy in describing...

31
לאוניד ברנבוים המחלקה למדעי המחשב אוניברסיטת בן- גוריוןMultiple Inheritance

Upload: others

Post on 06-Jun-2020

11 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

ברנבוים לאוניד

המחלקה למדעי המחשב

גוריון -אוניברסיטת בן

Multiple Inheritance

Page 2: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Roadmap

In this chapter we will investigate some of the

logical problems that can arise when a language

allows a child class to have multiple parents:

�Name ambiguity

�Impact on substitution

�The Problem of Common Ancestors

�Implementing multiple inheritance in Java

22

Page 3: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Inheritance as Categorization

33

Page 4: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

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

44

Page 5: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Inheritance as Combination

� Instead, real world objects are combinations of features from different classification schemes

� Each category giving some new insight into the whole:

Moshe is Male

Moshe is Israeli

Moshe is a Parent

Moshe is a Professor

� Note that we have not lost the is-a relationship; it still applies in each case

55

Page 6: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Inheritance as Combination

66

Male Professor

Parent

Israeli

Page 7: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Is-a, Has-a, and As-a

77

� A common analogy in describing multiple inheritance is that of an actor playing different roles

� Often at the same time

� Likewise, multiple inheritance is not has-a and not quite the is-a relationship (because the parent class is no longer unique)

� But a variation of the is-a that could be described as as-a

� Rule of thumb:

use multiple inheritance if the “A can be viewed as-a B” sounds right

Page 8: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

CS Example - Complex Numbers

Two abstract classifications:

� Magnitude - things that can be compared

� Number - things that can perform arithmetic

Three specific classes:

� Integer - comparable and arithmetic

� Char - comparable but not arithmetic

� Complex - arithmetic but not comparable

88

Page 9: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

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 (partial

flattening)

4. Make Number and Magnitude independent, and have Integer

inherit from both (multiple inheritance)

99

Page 10: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Inheritance as a form of

Combination

1010

Magnitude

Char

NumberInteger

Complex

This reflects the as-a relationship in a natural way

Page 11: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Another Example - Walking Menus

� A Menu is a structure charged with displaying itself

when selected by the user

� A Menumaintains a collection of MenuItems

� Each MenuItem knows how to respond when

selected

� A CascadingMenu is both

a MenuItem and a Menu

1111

Page 12: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Problem with Multiple Inheritance

- Name Ambiguity

What happens when the same name is used in both parent

classes:

�A CardDeck knows how to draw a Card

�A GraphicalItem knows how to draw an Image on a screen

�A GraphicalCardDeck should be able to draw

�Which?

1212

CardDeck

draw()

GraphicalObject

draw()

GraphicalCardDeck

?

Page 13: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Solution A

1313

Explicit disambiguation:

This solution is less than ideal, since the syntax is

different from other function calls,

and programmers must remember which method

comes from which parent

GraphicalCardDeck gcd;

gcd.CardDeck::draw();

gcd.GraphicalObject::draw();

Page 14: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Solution B1414

With different type signatures, can use straight overloading:

If the type signature are similar, or if overloading is not allowed, then the programmer is faced a more difficult decision.

class GCD : public CardDeck, public GraphicalObject {

public:

virtual Card *draw(){

return CardDeck::draw();

};

virtual void draw(GraphicsContext *g){

GraphicalObject::draw(g);

};

};

Page 15: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Solution C

Redefine one or the other operation in the child

class:

1515

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

Page 16: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Problem with

Redefinition Solution

� The redefinition solution is not without cost

� What happens when we run up against the

principle of substitution?

� This problem can be mitigated, but the solution

is complex and not perfect (see next slide)

1616

GraphicalObject *g = new GraphicalCardDeck();

g->draw(); // opps, doing wrong method!

Page 17: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

1717

class GraphicalCardDeck: public CardDeckParent, GraphicalObjectParent {

public:

virtual void cardDeckDraw() {…}

virtual void goDraw() {…}

}

class CardDeckParent : public CardDeck {

public:

virtual void draw() {cardDeckDraw();}

virtual void cardDeckDraw() {CardDeck::draw()}

}

class GraphicalObjectParent : public GraphicalObject {

public:

virtual void draw() {goDraw();}

virtual void goDraw() {GraphicalObject::draw()}

}

class CardDeckParent : public CardDeck {

public:

virtual void draw() {cardDeckDraw();}

virtual void cardDeckDraw() {CardDeck::draw()}

}

class GraphicalObjectParent : public GraphicalObject {

public:

virtual void draw() {goDraw();}

virtual void goDraw() {GraphicalObject::draw()}

}

// All three variables refer to the same object

GraphicalCardDeck *gcd = new GraphicalCardDeck();

CardDeck *cd = gcd;

GraphicalObject *go=gcd;

cd->draw(); // ok, will execute cardDeckDraw

go->draw(); // ok, will execute goDraw

gcd->draw(); // compiler error, ambiguous invocation

// All three variables refer to the same object

GraphicalCardDeck *gcd = new GraphicalCardDeck();

CardDeck *cd = gcd;

GraphicalObject *go=gcd;

cd->draw(); // ok, will execute cardDeckDraw

go->draw(); // ok, will execute goDraw

gcd->draw(); // compiler error, ambiguous invocation

A (complicated?) solution

Page 18: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

1818

class GraphicalCardDeck : CardDeck, GraphicalObject {

void CardDeck.draw() { … }

void GraphicalObject.draw() {…}

public void draw() { … }

}

class GraphicalCardDeck : CardDeck, GraphicalObject {

void CardDeck.draw() { … }

void GraphicalObject.draw() {…}

public void draw() { … }

}

A solution in C#

GraphicalCardDeck theDeck = new GraphicalCardDeck();

theDeck.draw(); // Executes method #3

CardDeck cd = (CardDeck) theDeck;

cd.draw(); // Executes method #1

GraphicalObject go = (GraphicalObject) theDeck;

go.draw(); // Executes method #2

GraphicalCardDeck theDeck = new GraphicalCardDeck();

theDeck.draw(); // Executes method #3

CardDeck cd = (CardDeck) theDeck;

cd.draw(); // Executes method #1

GraphicalObject go = (GraphicalObject) theDeck;

go.draw(); // Executes method #2

Page 19: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Other Approaches to

Name Ambiguity

Other languages use different approaches to solving the problem of ambiguous names:

�Eiffel uses the ability to rename features from the parent class

A polymorphic variable accessing through the parents name will access the renamed feature in the child (see next slide)

�LISP and Python resolve ambiguous names by the order in which the parent classes are listed

The first occurrence of the name found in a systematic search is the one selected

1919

Page 20: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Methods redefinition in Eiffel

2020

Eiffel allows to directly redefine a method in the sub-class by

renaming it in the inherit clause:

�The solution is roughly equivalent to helper renaming (having a

specific parent for each inherited copy)

�But more efficient and does not require extra classes

class GraphicalCardDeck

inherit

CardDeck

rename

draw as cardDeckDraw

end

GraphicalObject

rename

draw as goDraw

end

Page 21: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Multiple Inheritance of Interfaces

Multiple inheritance of interfaces does not present the same problem of

name ambiguity as does multiple inheritance of classes:

Either the ambiguous methods in the parent classes have different type signatures,

in which case there is no problem, or

The ambiguous methods in the parent classes have the same signature

Still no problem, since what is inherited is only a specification, not an

implementation

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.

2121

Page 22: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Inheritance from

Common Ancestors

2222

AA

CC

DD

BB

Does the new object have one or two instances of the ancestor?

AA

CC

DD

BB

AA

Page 23: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Sometimes: one instance

of the ancestor

2323

Page 24: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Sometimes: two instances

of the ancestor

2424

class Link{

public: Link *nextLink;

}

class CardDeck : public Link { … };

class GraphicalObject : public Link{ … };

Presumably, the lists of card decks and graphical objects are distinct, and hence each type of list should have its own links

Page 25: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

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 are two

� Not a perfect solution, and makes the language complicated

2525

Page 26: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Virtual InheritanceVirtual InheritanceVirtual InheritanceVirtual Inheritance

2626

� The ambiguity occurs in InOutStream,

� But the solution involves the definitions of InStreamand OutStream

class Stream {...};

class InStream: public virtual Stream {...};

class OutStream: public virtual Stream {...};

class InOutStream:

public InStream, public OutStream {...};

Page 27: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Inner Classes

The ability to nest classes in C++ and Java provides a mechanism

that is nearly equivalent to multiple inheritance, without the

semantic problems:

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 multiple inheritance

Not exactly equivalent to multiple inheritance, but very close

2727

class Child extends ParentOne {

...

class InnerChild extends ParentTwo {

...

// can access both parents

}

}

Page 28: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

DelegationSimulating Multiple Inheritance with Interfaces

2828

� Using interfaces and fields can simulate multiple inheritance.

� For example, we would like class C to extend both A and B

� Impossible multiple inheritance in Java:

class A {

public void foo() {...}

}

class B {

public void goo() {...}

}

class C extends A, B { // Not allowed in Java!

}

Page 29: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

DelegationAn alternative mechanism for “extending” classes

2929

To make class C “extend" B:

1)Define an interface BInf that includes

all the public methods of B

2)Make classes B and C implement BInf

3)Add a field of type B to class C

4)Implement BInf in C by delegating all

the messages to the new field

To make class C “extend" B:

1)Define an interface BInf that includes

all the public methods of B

2)Make classes B and C implement BInf

3)Add a field of type B to class C

4)Implement BInf in C by delegating all

the messages to the new field

Page 30: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

DelegationA Delegation example in Java

3030

class A {

public void foo() {...}

}

interface BInf {

void goo();

}

class B implements BInf {

public void goo {...}

}

class C extneds A implements BInf

{

private B _b;

public void goo() {

_b.goo();

}

}

Page 31: Multiple Inheritance - BGUoosd132/wiki.files/Lecture10.pdf · A common analogy in describing multiple inheritance is that of an actor playing different roles Often at the same time

Chapter Summary

In this chapter we have explored some of the

problems that arise of the concept of multiple

inheritance:

� Name ambiguity

� Impact on substitution

� The problem of common ancestors

� Implementing multiple inheritance in Java

3131