CSC/ECE 517 Fall 2012/ch1 1w14 gv: Difference between revisions
Line 26: | Line 26: | ||
3. Multiple inheritance might lead to a higher possibility of code reuse. Every additional base class enhances code reuse. Without MI, we would be forced to use the has-a relationship, thereby reducing code reuse factor (increases implementation and testing time). | 3. Multiple inheritance might lead to a higher possibility of code reuse. Every additional base class enhances code reuse. Without MI, we would be forced to use the has-a relationship, thereby reducing code reuse factor (increases implementation and testing time). | ||
= Alternatives = | |||
1. Modules: A module is a collection of methods and constants. Modules can have no sub classes and instances. One of the major uses of modules is to encapsulate the methods and constants in one location. Modules provide namespace and also prevent name clashes. Ruby's built in modules like Math exhibit these features. For example, | 1. Modules: A module is a collection of methods and constants. Modules can have no sub classes and instances. One of the major uses of modules is to encapsulate the methods and constants in one location. Modules provide namespace and also prevent name clashes. Ruby's built in modules like Math exhibit these features. For example, | ||
Line 42: | Line 42: | ||
Another use of modules is mixins. | Another use of modules is mixins. | ||
2. Mixin inheritance: A mixin is a class that encapsulates additional attributes or properties which can be used by other classes. Mixins are typically narrow in scope (include only a few properties) and a class might inherit several mixins (for several properties). Mixins have a clear advantage in terms of modularity and reusability. Mixins cannot be instantiated independently (cannot stand on their own) and are not instantiated directly, as they might depend on the presence of a particular interface in the classes that inherit them. Generally, mixins are self contained. | 2. Mixin inheritance: A mixin is a class that encapsulates additional attributes or properties which can be used by other classes. Mixins are typically narrow in scope (include only a few properties) and a class might inherit several mixins (for several properties). Mixins have a clear advantage in terms of modularity and reusability. | ||
Mixins cannot be instantiated independently (cannot stand on their own) and are not instantiated directly, as they might depend on the presence of a particular interface in the classes that inherit them. Generally, mixins are self contained. | |||
Multiple Inheritance and Mixins differ in semantics. A class which uses multiple inheritance might utilize a mixin as a part of that multiple inheritance. Mixins can be thought of as an interface that is already implemented. We "include" a module in a class definition, its methods are effectively appended, or "mixed in" to the class. | Multiple Inheritance and Mixins differ in semantics. A class which uses multiple inheritance might utilize a mixin as a part of that multiple inheritance. Mixins can be thought of as an interface that is already implemented. We "include" a module in a class definition, its methods are effectively appended, or "mixed in" to the class. | ||
Languages like C#, Perl, Python, Ruby take advantage of mixins. Languages like JavaScript do not support mixins but can copy methods from one object to other at run time thereby emulating mixins. | Languages like C#, Perl, Python, Ruby take advantage of mixins. Languages like JavaScript do not support mixins but can copy methods from one object to other at run time thereby emulating mixins. |
Revision as of 21:26, 14 September 2012
Introduction
Multiple inheritance is one of the features of a few object-oriented (OO) languages in which a class inherits properties (variables & methods) from more than one parent class . The former is called a sub or child class and the latter is called a super class or ancestor class. Multiple Inheritance extends the concept of single inheritance (where one sub class inherits the properties from one super class) to a paradigm where one child class will inherit properties from multiple parent classes.
For example, consider a class to describe teaching assistants. A TA class will draw a lot of properties from both Student and University employee classes. So, instead of implementing them again, we can programmatically specify that class TGradTeachingAsst extends both Student and Employee classes
This feature is supported by several object oriented languages such as C++, Eiffel, Perl, Python etc. On the other hand, some object oriented languages like C#, Smalltalk, Java, Modula-3, Objective C etc. do not support multiple inheritance. Multiple inheritance is still a debatable feature in traditional object-oriented languages, as it has been omitted from languages like Java etc. Nonetheless, users of these languages often complain about having to work around the absence of multiple inheritance. Multiple inheritance, if used wisely could be advantageous. On the other hand, if the developers are not smart enough to use it, it could lead to a lot of complexities.
Advantages
Multiple inheritance is widely considered a useful feature as it is commonly used in the above listed OO languages. It is also a frequently requested feature in languages that do not provide it. Programmers often devise their own workaround procedures to achieve what multiple inheritance offers. One of the advantages of multiple inheritance is that it obviates improvised solutions that would otherwise be fairly obvious.
Following uses of multiple inheritance are desirable, all of which are supported :
1. Multiple specialization: An instance of a class that is derived by multiple inheritance can be conceptually thought of as a specialization of two different classes. For example, a class InputOutputStream is a specialization of both an InputStream and OutputStream. In general, multiple inheritance allows us to combine classes to create new abstractions, and these new abstractions are of more value than the individual abstractions by themselves.
2. Multiple inheritance also helps in modeling relationships that are multi way. Without MI, a choice has to be made among the many possible relationships, even though all of them are valid. When a class needs properties found in more than one base class, MI might be useful.
3. Multiple inheritance might lead to a higher possibility of code reuse. Every additional base class enhances code reuse. Without MI, we would be forced to use the has-a relationship, thereby reducing code reuse factor (increases implementation and testing time).
Alternatives
1. Modules: A module is a collection of methods and constants. Modules can have no sub classes and instances. One of the major uses of modules is to encapsulate the methods and constants in one location. Modules provide namespace and also prevent name clashes. Ruby's built in modules like Math exhibit these features. For example, Math::E gives the value of e(base of natural logarithms). The '::' operator tells the ruby interpreter which module it should look up for the value of E. Syntax to define a module:
module <Module_Name> //constants //methods end
Methods and constants in modules are declared just like they are declared in class. Another use of modules is mixins.
2. Mixin inheritance: A mixin is a class that encapsulates additional attributes or properties which can be used by other classes. Mixins are typically narrow in scope (include only a few properties) and a class might inherit several mixins (for several properties). Mixins have a clear advantage in terms of modularity and reusability. Mixins cannot be instantiated independently (cannot stand on their own) and are not instantiated directly, as they might depend on the presence of a particular interface in the classes that inherit them. Generally, mixins are self contained. Multiple Inheritance and Mixins differ in semantics. A class which uses multiple inheritance might utilize a mixin as a part of that multiple inheritance. Mixins can be thought of as an interface that is already implemented. We "include" a module in a class definition, its methods are effectively appended, or "mixed in" to the class. Languages like C#, Perl, Python, Ruby take advantage of mixins. Languages like JavaScript do not support mixins but can copy methods from one object to other at run time thereby emulating mixins. Following example shows how to use mixins in a class:
module A def a1 puts “Method a1” end def a2 puts “Method a2” end end module B def b1 puts “Method b1” end def b2 puts “Method b2” end end module C def c1 puts “Method c1” end def c2 puts “Method c2” end end class Example include A include B def e1 end end exp = Example.new // Creating a new object of Example class exp.a1 // Calling a1 method of module A exp.a2 // Calling a2 method of module A exp.b1 // Calling b1 method of module B exp.b2 // Calling b2 method of module B exp.c1 // Calling c1 method of module C exp.c2 // Calling c2 method of module C exp.e1 // Calling e1 method defined inside class Example
Each module A, B and C have two methods a1, a2, b1, b2 and c1, c2 respectively. "include" is the keyword used in Ruby to embed a module in a class. The class Example includes modules A, B and C. Thus, an object of the class Example can access all the methods in A, B and C modules. We can see that Example class shows multiple inheritance or a mixin.
Comparison between C++/Java/Python/Ruby
Multiple Inheritance is supported by several object oriented languages such as C++, Ruby, Perl, Python etc. Let us compare how multiple inheritance is implemented in each of these languages.
C++
In C++, multiple inheritance is achieved by using the colon (:) operator to extend different base classes.
class Person { private: std::string m_strName; int m_nAge; public: Person(std::string strName, int nAge, : m_strName(strName), m_nAge(nAge) { } std::string GetName() { return m_strName; } int GetAge() { return m_nAge; } bool IsMale() { return m_bIsMale; } }; class Employee { private: std::string m_strEmployer; double m_dWage; public: Employee(std::string strEmployer, double dWage) : m_strEmployer(strEmployer), m_dWage(dWage) { } std::string GetEmployer() { return m_strEmployer; } double GetWage() { return m_dWage; } }; // Teacher publicly inherits Person and Employee class Teacher: public Person, public Employee { private: int m_nTeachesGrade; public: Teacher(std::string strName, int nAge, std::string strEmployer, double dWage, int nTeachesGrade) : Person(strName, nAge), Employee(strEmployer, dWage), m_nTeachesGrade(nTeachesGrade) { } };
In the above example, the "Teacher" class extends the properties of both Person and Employee classes. Thus, an object of "Teacher" class can use the public methods of both the "Person" and "Employee "classes.
Python
Python supports a limited form of multiple inheritance. The parent classes are included within parenthesis following the class name. The following example demonstrates multiple inheritance in Python:
class First(object): def __init__(self): print "first" class Second(First): def __init__(self): print "second" class Third(First): def __init__(self): print "third" class Fourth(Second, Third): def __init__(self): super(Fourth, self).__init__() print "that's it"
In Python, parent method does not automatically get called. If methods are overriden, the parent version of method should be called. The keyword "super" is used to call the parent's method. In the above Python example, class "Fourth" inherits classes "Second" and "Third" . The order in which classes are called in the above example is Fourth, Second, Third, First.
Ruby
Link to the mixin example
Java
Java, another OO language, does not support multiple inheritance. But interfaces in Java can be used to emulate multiple inheritance. Java uses the "extends" keyword to inherit a base class and the keyword "implements" for interfaces.
interface I1 { abstract void test(int i); } interface I2 { abstract void test(String s); } public class C1 { public void test(float f) { float f = this.f; } } public class MultInterfaces extends C1 implements I1, I2 { public void test(int i) { System.out.println("In MultInterfaces.I1.test"); } public void test(String s) { System.out.println("In MultInterfaces.I2.test"); } public static void main(String[] a) { MultInterfaces t = new MultInterfaces(); t.test(42); // calls the implemented interface I1 method t.test("Hello"); // calls the implemented interface I2 method t.test(1.42); // calls the class C1 method } }
In Java, a class cannot extend two classes, but can implement more than 1 interfaces. The methods in the interfaces should be implemented by the class using them. In the above example C1 is a parent class, I1 and I2 are interfaces with abstract methods. Objects of the MultInterfaces class can be created only if it implements abstract methods from interfaces I1 and I2.
References
http://www.tutorialspoint.com/ruby/ruby_modules.htm http://www.ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/modules.html http://docs.python.org/tutorial/classes.html#multiple-inheritance http://www.tutorialspoint.com/ruby/ruby_modules.htm