Multiple inheritance
From Wikipedia, the free encyclopedia
Multiple inheritance refers to a feature of some object-oriented programming languages in which a class can inherit behaviors and features from more than one superclass. This contrasts with single inheritance, where a class may inherit from at most one superclass.
Languages that support multiple inheritance include: Eiffel, C++, Dylan, Python, Perl, Curl, Common Lisp (via CLOS), OCaml, and Tcl (via Incremental TCL)[1].
Contents |
[edit] Overview
Multiple inheritance allows a class to take on functionality from multiple other classes, such as allowing a class named StudentMusician
to inherit from a class named Person
, a class named Musician
, and a class named Worker
. This can be abbreviated StudentMusician : Person, Musician, Worker
.
Ambiguities arise in multiple inheritance, as in the example above, if for instance the class Musician inherited from Person and Worker and the class Worker inherited from Person. This is referred to as the Diamond problem. There would then be the following rules:
Worker : Person Musician : Person, Worker StudentMusician : Person, Musician, Worker
If a compiler is looking at the class StudentMusician it needs to know whether it should join identical features together, or whether they should be separate features. For instance, it would make sense to join the "Age" features of Person together for StudentMusician. A person's age doesn't change if you consider them a Person, a Worker, or a Musician. It would, however, make sense to separate the feature "Name" in Person and Musician if they use a different stage name than their given name. The options of joining and separating are both valid in their own context and only the programmer knows which option is correct for the class they are designing.
Languages have different ways of dealing with these problems of repeated inheritance.
- Eiffel allows the programmer to explicitly join or separate features that are being inherited from superclasses. Eiffel will automatically join features together if they have the same name and implementation. The class writer has the option to rename the inherited features to separate them. Eiffel also allows explicit repeated inheritance such as A: B, B.
- C++ requires that the programmer state which parent class the feature to use should come from i.e. "Worker::Person.Age". C++ does not support explicit repeated inheritance since there would be no way to qualify which superclass to use (see criticisms). C++ also allows a single instance of the multiple class to be created via the virtual inheritance mechanism (i.e. "Worker::Person" and "Musician::Person" will reference the same object).
- Perl uses the list of classes to inherit from as an ordered list. The compiler uses the first method it finds by depth-first searching of the superclass list or using the C3 linearization of the class hierarchy. Various extensions provide alternative class composition schemes. Python has the same structure, but unlike Perl includes it in the syntax of the language. In Perl and Python, the order of inheritance affects the class semantics (see criticisms).
- The Common Lisp Object System allows full programmer control of method combination, and if this is not enough, the Metaobject Protocol gives the programmer a means to modify the inheritance, method dispatch, class instantiation, and other internal mechanisms without affecting the stability of the system.
- Logtalk supports both interface and implementation multi-inheritance, allowing the declaration of method aliases that provide both renaming and access to methods that would be masked out by the default conflict resolution mechanism.
- Curl allows only classes that are explicitly marked as shared to be inherited repeatedly. Shared classes must define a secondary constructor for each regular constructor in the class. The regular constructor is called the first time the state for the shared class is initialized through a subclass constructor, and the secondary constructor will be invoked for all other subclasses.
- Ocaml chooses the last matching definition of a class inheritance list to resolve which method implementation to use under ambiguities. To override the default behavior one simply qualifies a method call with the desired class definition.
- Tcl allows multiple parent classes- their serial affects the name resolution for class members.[2]
C#, Objective-C, Object Pascal / Delphi, Java, Nemerle, and PHP do not allow multiple inheritance, and this avoids any ambiguity. However, these six languages allow classes to inherit from multiple interfaces, recreating some of the problems mentioned while avoiding others.
[edit] Criticisms
Multiple inheritance has received criticism and as such, is not implemented in many languages. Criticisms includes:
- Increased complexity
- Semantic ambiguity often summarized as the diamond problem.[3]
- Not being able to explicitly inherit multiple times from a single class[citation needed]
- Order of inheritance changing class semantics.
Multiple inheritance in languages with C++/Java style constructors exacerbates the inheritance problem of constructors and constructor chaining, thereby creating maintenance and extensibility problems in these languages. Objects in inheritance relationships with greatly varying construction methods are hard to implement under the constructor chaining paradigm.
[edit] See also
[edit] References
[edit] Further reading
- Stroustrup, Bjarne (1999). Multiple Inheritance for C++. Proceedings of the Spring 1987 European Unix Users Group Conference.
- Object-Oriented Software Construction, Second Edition, by Bertrand Meyer, Prentice Hall, 1997, ISBN 0-13-629155-4