180 likes | 193 Views
Explore the concepts of inheritance as classification, combination, and the controversy surrounding multiple inheritance in programming. Learn about resolving ambiguity in inheritance hierarchies.
E N D
CSCI-383 Object-Oriented Programming & Design Lecture 19
Inheritance as Classification • In one way, the is-a relationship is a form of classification • E.g., A TextFile is a type of File so class TextFile inherits from class File File TextFile
Inheritance as Classification • But in the real world, most objects can be categorized in a variety of ways. A person can be a • Male • Professor • Parent • None of these are proper subsets of the other, and we cannot make a single rooted inheritance hierarchy out of them
Inheritance as Combination • Instead, real world objects are combinations of many nonoverlapping categories, each category contributing something to the result • Note that we have not lost the is-a relationship; it still applies in each case Male Professor Parent
Multiple Inheritance • Modeling this behavior in programs seems to call for the concept of multiple inheritance • An object can have two or more different parent classes and inherit both data and behavior from each Male Professor Parent
Multiple Inheritance • It wouldn't be an exaggeration to say that multiple inheritance has stirred more controversy and heated debates than has any other C++ feature • Yet the truth is that multiple inheritance is a powerful and effective feature -- when used properly • What is a good model?
Incomparable Complex Numbers • A portion of the Smalltalk class hierarchy things that can be compared to each other Object Boolean Magnitude Collection True False Char Number Point Set KeyedCollection Integer Float Fraction things that can perform arithmetic
Possible Solutions • Make Number subclass of Magnitude, but redefine comparison operators in class Complex to give error message if used (e.g., subclassing for limitation) • Don't use inheritance at all -- redefine all operators in all classes (e.g., flattening the inheritance tree) • Use part inheritance, but simulate others (e.g., use Number, but have each number implement all relational operators) • Make Number and Magnitude independent, and have Integer inherit from both (i..e, multiple inheritance)
Possible Solutions Magnitude Number Char Integer Complex
Another Example – Walking Menus • A Menu is a structure charged with displaying itself when selected by the user • A Menu maintains a collection of MenuItems • Each MenuItem knows how to respond when selected • A cascading menu is both a MenuItem and a Menu
Multiple Inheritance in C++ • C++ supports multiple inheritance (i.e., a class may be derived from more than one base class) • C++ syntax: class Derived: public Base1, public Base2, public Base3, protected Base4 { ... }; • Example: class passengerVehicle { ... }; class trainCar { ... }; class passengerCar: public passengerVehicle, public trainCar { ... }; • Handout #6
The Ambiguity Problem • Circumstances: Let Derived be inherited from Base1 and Base2 • All feature names inside Base1 are distinct • All feature names inside Base2 are distinct • All feature names inside Derivedshould be distinct • Ambiguity problem: the same feature name X occurs both in Base1 and in Base2 • The problem does not occur in single inheritance • If the same feature name occurs both in Derived and in Base, then no ambiguity occurs. Why?
The Ambiguity Problem • In handout #6, what would happen if we attempted to print the data members of derived by accessing them individually instead of using the overloaded operator<< cout << “Object derived contains:\n” << “Integer: “ << derived.getData() << “\nCharacter: “ << derived.getData() << “\nReal number: “ << derived.getReal() << “\n\n“;
Coincidental vs. Inherent Ambiguity • Coincidental ambiguity occurs when the duplicated names Base1::X and Base2::X are unrelated • Ambiguity is a coincidence • Same name, distinct entities • Inherent ambiguity occurs when Base1 and Base2 derive from a common Base, in which X occurs • Ambiguity is inherent • Same name, same entity
Ambiguity Resolution Approaches • Forbid the inheritance as given. Force the designer of Base1 and/or Base2 to resolve the ambiguity • Unreasonable: Good names are rare. In many cases, multiple inheritance marries together two distinct inheritance hierarchies, sometimes supplied by different vendors • Impossible: In cases of repeated inheritance • Force the designer of Derived to resolve all ambiguities • In Eiffel, the compiler does not allow a class in which an ambiguity exists. The designer must rename all ambiguous features • In C++, a good designer will override all ambiguous features. This is not always possible since one cannot override data members
Ambiguity Resolution in C++ • Scenario • An inherited function/data member is used (inside or outside the class) • The compiler checks that the name is defined in exactly one (direct/indirect) base class • Error message produced if name is defined in more than one class • Ambiguity should be resolved before compilation can proceed • Use qualified names (::) to specify exactly one derived member
Ambiguity Resolution in C++ • In handout #6, if we wanted to print the data members of derived by accessing them individually instead of using the overloaded operator<<, we could use the scope resolution operator (::) to resolve the ambiguity cout << “Object derived contains:\n” << “Integer: “ << derived.Base1::getData() << “\nCharacter: “ << derived.Base2::getData() << “\nReal number: “ << derived.getReal() << “\n\n“; • Drawbacks • Client should be aware of implementation details • Late detection of errors