Jump to content

Multiple inheritance: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
Overview: Fixed typo
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
'''Multiple inheritance''' is a feature of some [[object-oriented programming|object-oriented]] computer [[programming language]]s in which a [[class (computer science)|class]] can [[inheritance (computer science)|inherit]] behaviors and features from more than one [[superclass (computer science)|superclass]].
'''Multiple inheritance''' is a feature of some [[object-oriented programming|object-oriented]] computer [[programming language]]s in which a [[class (computer science)|class]] can [[inheritance (computer science)|inherit]] behaviors and features from more than one [[superclass (computer science)|superclass]].
The ''class inheritance'' lets you generate a model that is closer to the real-world. The class inheritance lets you derive new classes (called ''derived classes'') from old ones, with the derived class inheriting the properties, including the methods of the old class, known as ''base class''.

The most important advantage of ''inheritance'' is code ''reusability''. Once a ''base class'' is written, it can be used anywhere and any how without having to redefine it or rewrite it. Already checked and previously written codes can be reused. Reusing existing code saves time, money, and efforts and the program becomes more efficient and reliable. Without redefining the old class, you can add new properties to the ''derived class'' and this makes '''''Multiple Inheritance''''' a very good structuring tool in C++.
<br />
When a '''''sub class''''' inherits from '''''multiple base classes''''', it is known as '''''multiple inheritance'''''. Fig. illustrates multiple inheritance.

[[File:Multiple Inheritance.pdf|center|thumb|400px * 400px|Multiple Inheritance]]


Languages that support multiple inheritance include: [[C++]], [[Common Lisp]] (via [[Common Lisp Object System|CLOS]]), [[EuLisp]] (via The EuLisp Object System TELOS), [[Curl (programming language)|Curl]], [[Dylan (programming language)|Dylan]], [[Eiffel (programming language)|Eiffel]], [[Logtalk]], [[Object REXX]], [[Scala (programming language)|Scala]] (via the use of [[Mixin|mixin classes]]), [[OCaml]], [[Perl]], [[Perl 6]], [[Python (programming language)|Python]], and [[Tcl]] (via [[Itcl|Incremental Tcl]]).<ref>[http://wiki.tcl.tk/590 Tcl Advocacy]</ref>
Languages that support multiple inheritance include: [[C++]], [[Common Lisp]] (via [[Common Lisp Object System|CLOS]]), [[EuLisp]] (via The EuLisp Object System TELOS), [[Curl (programming language)|Curl]], [[Dylan (programming language)|Dylan]], [[Eiffel (programming language)|Eiffel]], [[Logtalk]], [[Object REXX]], [[Scala (programming language)|Scala]] (via the use of [[Mixin|mixin classes]]), [[OCaml]], [[Perl]], [[Perl 6]], [[Python (programming language)|Python]], and [[Tcl]] (via [[Itcl|Incremental Tcl]]).<ref>[http://wiki.tcl.tk/590 Tcl Advocacy]</ref>
Line 9: Line 16:
In Multiple Inheritance a derived class can access members of more than one base class directly. Multiple inheritance allows a class to take on functionality from multiple other classes, such as allowing a class named <code>StreetMusician</code> to inherit from a class named <code>Human</code>, a class named <code>Musician</code>, and a class named <code>Worker</code>. This can be abbreviated <code>StreetMusician : Human, Musician, Worker</code>.
In Multiple Inheritance a derived class can access members of more than one base class directly. Multiple inheritance allows a class to take on functionality from multiple other classes, such as allowing a class named <code>StreetMusician</code> to inherit from a class named <code>Human</code>, a class named <code>Musician</code>, and a class named <code>Worker</code>. This can be abbreviated <code>StreetMusician : Human, Musician, Worker</code>.


Ambiguities arise in multiple inheritance, as in the example above, if for instance the class <code>Musician</code> inherited from <code>Human</code> and<code> Worker</code> and the class <code>Worker</code> inherited from <code>Human</code>. This is referred to as the [[Diamond problem]]. There would then be the following rules:
Ambiguities arise in multiple inheritance, as in the example above, if, for instance, the class <code>Musician</code> inherited from <code>Human</code> and<code> Worker</code> and the class <code>Worker</code> inherited from <code>Human</code>. This is referred to as the [[diamond problem]]. There would then be the following rules:


'''Worker ''' : Human
'''Worker ''' : Human
Line 30: Line 37:


[[C Sharp (programming language)|C#]], [[D (programming language)|D]], [[Object Pascal|Object Pascal / Delphi]], [[Java (programming language)|Java]], [[ActionScript]], [[Nemerle]], [[Objective-C]], [[Smalltalk]], and [[PHP]] do not allow multiple inheritance, and this avoids any ambiguity. However, all but [[Smalltalk]] allow classes to implement multiple [[Interface (Java)|interfaces]].
[[C Sharp (programming language)|C#]], [[D (programming language)|D]], [[Object Pascal|Object Pascal / Delphi]], [[Java (programming language)|Java]], [[ActionScript]], [[Nemerle]], [[Objective-C]], [[Smalltalk]], and [[PHP]] do not allow multiple inheritance, and this avoids any ambiguity. However, all but [[Smalltalk]] allow classes to implement multiple [[Interface (Java)|interfaces]].

== Need for Multiple Inheritance ==
''Inheritance'' is an important concept of object-oriented languages. There are several reasons why inheritance was introduced into object-oriented language. Some major reasons are :
* One of the reasons is the '''''expression of inheritance relationship''''' which sees that it closely resembles the real-world methods.
* Another important reason is the idea of '''''reusability'''''. The advantages of reusability are : ''faster processes, easier maintenance, and easy to extend''. One can derive a new class (''subclass or derived class'') from an existing one and add new features to it.
Suppose we have classes called ''College Students'' and ''Science Students'' and we need to add new class called ''Engineering Students''. We derive the new class ''Engineering Students'' from the existing classes ''College Students'' and ''Science Students'' and then all we do is add the distinguishing features to ''Engineering Students'' that differentiates between college, science students and engineering students. This reduces the amount of typing and efforts considerably.


<br />
* One reason is '''''transitive property of inheritance'''''. That is, ''if a class '''X''' is derived from another class '''W''', then all subclasses of '''X''' will automatically show the properties of class '''W'''. This property is called ''transitive'' nature of inheritance.
Suppose we derive class '''X''' from existing class '''W'''. The classes '''Y''' and '''Z''' inherit from class '''X'''. Later on we find that class '''W''' has a discrepancy(bug) that must be fixed. After fixing the problem in '''W''', it is automatically reflected across all classes that are derived(inherited) from '''W'''. This has indeed reduced the amount of efforts that one would have taken if each class derived from '''W''' was to be corrected separately. This makes ''transitiveness'' as one of the most important properties of Multiple Inheritance.


== C++ Implementation Strategy ==
== C++ Implementation Strategy ==

Revision as of 18:49, 12 October 2011

Multiple inheritance is a feature of some object-oriented computer programming languages in which a class can inherit behaviors and features from more than one superclass. The class inheritance lets you generate a model that is closer to the real-world. The class inheritance lets you derive new classes (called derived classes) from old ones, with the derived class inheriting the properties, including the methods of the old class, known as base class.

The most important advantage of inheritance is code reusability. Once a base class is written, it can be used anywhere and any how without having to redefine it or rewrite it. Already checked and previously written codes can be reused. Reusing existing code saves time, money, and efforts and the program becomes more efficient and reliable. Without redefining the old class, you can add new properties to the derived class and this makes Multiple Inheritance a very good structuring tool in C++.
When a sub class inherits from multiple base classes, it is known as multiple inheritance. Fig. illustrates multiple inheritance.

Multiple Inheritance

Languages that support multiple inheritance include: C++, Common Lisp (via CLOS), EuLisp (via The EuLisp Object System TELOS), Curl, Dylan, Eiffel, Logtalk, Object REXX, Scala (via the use of mixin classes), OCaml, Perl, Perl 6, Python, and Tcl (via Incremental Tcl).[1]

Other object-oriented languages, such as Java, implement single inheritance.

Overview

In Multiple Inheritance a derived class can access members of more than one base class directly. Multiple inheritance allows a class to take on functionality from multiple other classes, such as allowing a class named StreetMusician to inherit from a class named Human, a class named Musician, and a class named Worker. This can be abbreviated StreetMusician : Human, Musician, Worker.

Ambiguities arise in multiple inheritance, as in the example above, if, for instance, the class Musician inherited from Human and Worker and the class Worker inherited from Human. This is referred to as the diamond problem. There would then be the following rules:

Worker         :  Human
Musician       :  Human, Worker
StreetMusician :  Human, Musician, Worker

If a compiler is looking at the class StreetMusician, 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 Human together for StreetMusician. A human's age doesn't change, if you consider them a human, a worker, or a musician. It would, however, make sense to separate the feature "Name" in Human 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.

  • C++ requires the programmer to state which parent class the feature to be used is invoked from i.e. "Worker::Human.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::Human" and "Musician::Human" will reference the same object).
  • 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.
  • 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.
  • 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.
  • 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.
  • 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.
  • 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. The order of inheritance affects the class semantics (see criticisms).
  • Python has the same structure as Perl, but unlike Perl includes it in the syntax of the language. The order of inheritance affects the class semantics (see criticisms).
  • Scala allows multiple instantiation of traits, which allows for multiple inheritance by adding a distinction between the class hierarchy and the trait hierarchy. A class can only inherit from a single class, but can mix-in as many traits as desired.
  • Tcl allows multiple parent classes- their serial affects the name resolution for class members.[2]

C#, D, Object Pascal / Delphi, Java, ActionScript, Nemerle, Objective-C, Smalltalk, and PHP do not allow multiple inheritance, and this avoids any ambiguity. However, all but Smalltalk allow classes to implement multiple interfaces.

Need for Multiple Inheritance

Inheritance is an important concept of object-oriented languages. There are several reasons why inheritance was introduced into object-oriented language. Some major reasons are :

  • One of the reasons is the expression of inheritance relationship which sees that it closely resembles the real-world methods.
  • Another important reason is the idea of reusability. The advantages of reusability are : faster processes, easier maintenance, and easy to extend. One can derive a new class (subclass or derived class) from an existing one and add new features to it.

Suppose we have classes called College Students and Science Students and we need to add new class called Engineering Students. We derive the new class Engineering Students from the existing classes College Students and Science Students and then all we do is add the distinguishing features to Engineering Students that differentiates between college, science students and engineering students. This reduces the amount of typing and efforts considerably.



  • One reason is transitive property of inheritance. That is, if a class X is derived from another class W, then all subclasses of X will automatically show the properties of class W. This property is called transitive nature of inheritance.

Suppose we derive class X from existing class W. The classes Y and Z inherit from class X. Later on we find that class W has a discrepancy(bug) that must be fixed. After fixing the problem in W, it is automatically reflected across all classes that are derived(inherited) from W. This has indeed reduced the amount of efforts that one would have taken if each class derived from W was to be corrected separately. This makes transitiveness as one of the most important properties of Multiple Inheritance.

C++ Implementation Strategy

Before discussing multiple inheritance and its implementation in C++ let's first describe the main points in the traditional implementation of the C++ single inheritance class concept. An object of a C++ class is represented by a contiguous region of memory. A pointer to an object of a class points to the first byte of that region of memory. The compiler turns a call of a member function into an ‘‘ordinary’’ function call with an ‘‘extra’’ argument; that ‘‘extra’’ argument is a pointer to the object for which the member function is called. Consider a simple class A†:

class A {
int a;
void f(int i);
};

An object of class A will look like this

-----------------
| int a; |
-----------------

No information is placed in an A except the integer a specified by the user. No information relating to (non-virtual) member functions is placed in the object. A call of the member function A::f: A* pa; pa->f(2); is transformed by the compiler to an ‘‘ordinary function call’’: f__F1A(pa,2); Objects of derived classes are composed by concatenating the members of the classes involved:

class A { int a; void f(int); };
class B : A { int b; void g(int); };
class C : B { int c; void h(int); };

Again, no ‘‘housekeeping’’ information is added, so an object of class C looks like this:

-----------------
| int a; |
| int b; |
| int c; |
-----------------

The compiler ‘‘knows’’ the position of all members in an object of a derived class exactly as it does for an object of a simple class and generates the same (optimal) code in both cases. Implementing virtual functions involves a table of functions. Consider:

class A {
int a;
virtual void f(int);
virtual void g(int);
virtual void h(int);
};
class B : A { int b; void g(int); };
class C : B { int c; void h(int); };

In this case, a table of virtual functions, the vtbl, contains the appropriate functions for a given class and a pointer to it is placed in every object. A class C object looks like this:

-----------------
| int a; | vtbl:
| vptr .........> -----------------
| int b; | | A::f |
| int c; | | B::g |
----------------- | C::h |
-----------------

A call to a virtual function is transformed into an indirect call by the compiler. For example, C* pc; pc->g(2); becomes something like: (*(pc->vptr[1]))(pc,2); A multiple inheritance mechanism for C++ must preserve the efficiency and the key features of this implementation scheme.

Criticisms

Multiple inheritance has been criticized by some for its unnecessary complexity and being difficult to implement efficiently, though some projects have certainly benefited from its use. Java, for example has no multiple inheritance, as its designers felt that it would add unnecessary complexity. Java instead allows inheriting from multiple pure abstract classes (called interfaces in Java). Or one could use a mixin.

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[citation needed]. Objects in inheritance relationship with greatly varying construction methods are hard to implement under the constructor-chaining paradigm.

Criticisms for the problems that it causes in certain languages, in particular C++, are:

  • Semantic ambiguity often summarized as the diamond problem (although solvable by using virtual inheritance or 'using' declarations).[3]
  • Not being able to explicitly inherit multiple times from a single class (on the other hand this feature is criticised as non-object-oriented).[citation needed]
  • Order of inheritance changing class semantics (although it's the same with order of field declarations).[citation needed]

See also

References

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