CSC/ECE 517 Fall 2010/ch3 3b ka: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(33 intermediate revisions by 2 users not shown)
Line 5: Line 5:
[http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_25_ag#What_is_Multiple_Inheritance Multiple inheritance] is often deemed as a very powerful tool in the [http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_1e_bb#Object_Oriented_Programming Object Oriented Programming] paradigm. Implementation of multiple inheritance in languages like [http://en.wikipedia.org/wiki/Java_(programming_language) Java] ([http://download.oracle.com/javase/tutorial/java/concepts/interface.html interfaces]) and [http://en.wikipedia.org/wiki/C%2B%2B C++] is restricted and can often lead to a number of difficulties like the [http://en.wikipedia.org/wiki/Diamond_problem Diamond Problem], [http://en.wikipedia.org/wiki/Virtual_inheritance Virtual Inheritance] issue and increase in programming complexity.  
[http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_25_ag#What_is_Multiple_Inheritance Multiple inheritance] is often deemed as a very powerful tool in the [http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_1e_bb#Object_Oriented_Programming Object Oriented Programming] paradigm. Implementation of multiple inheritance in languages like [http://en.wikipedia.org/wiki/Java_(programming_language) Java] ([http://download.oracle.com/javase/tutorial/java/concepts/interface.html interfaces]) and [http://en.wikipedia.org/wiki/C%2B%2B C++] is restricted and can often lead to a number of difficulties like the [http://en.wikipedia.org/wiki/Diamond_problem Diamond Problem], [http://en.wikipedia.org/wiki/Virtual_inheritance Virtual Inheritance] issue and increase in programming complexity.  


Mixins provide a way to mimic the functionality of multiple inheritance without inheriting the limitations of traditional multiple inheritance. Mixins can be found in languages like [http://www.ruby-lang.org/en/ Python], [http://www.scala-lang.org/ Scala], [http://www.ruby-lang.org/en/ Ruby] etc.
Mixins provide a way to mimic the functionality of multiple inheritance without inheriting the limitations of traditional multiple inheritance. Mixins can be found in languages like [http://www.python.org/ Python], [http://www.scala-lang.org/ Scala], [http://www.ruby-lang.org/en/ Ruby] etc.


=Mixins=
=Mixins=
Line 30: Line 30:
==Diamond Problem==
==Diamond Problem==


Earlier we had discussed the [http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_25_ag#Diamond_Problem_in_Detail Diamond Problem] and its impact on [http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_25_ag multiple inheritance. Here is how the scenario changes with the usage of mixins. Consider an example where
Earlier we had discussed the  
[http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_25_ag#Diamond_Problem_in_Detail Diamond Problem] and its impact on [http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch1_25_ag multiple inheritance]. Here is how the scenario changes with the usage of mixins in Ruby. When ever any ambiguity arises with regard to method inheritance, the method that was included last is considered. Hence the need for virtual inheritance is alleviated.  


One very common problem with multiple inheritance is called the Diamond Problem. This can be illustrated with the following example:
This can be illustrated with the following example. Consider a module A in inherited by modules B and C.


Say two classes B & C both inherit from A and D inherits from B & C. Suppose in class D an object calls a method defined in class A, where B & C have overridden the method, then there is the problem of which class does it inherit from, B or C? The Diamond Problem is solved using virtual inheritance in languages like C++.  This is taken care of in Ruby, as the method with the same name that was most recently included would be considered. Hence there is no need of virtual inheritance.
  module A
This is demonstrated by the following example:
      def goodbye
        puts "hello"
      end
  end


module A
  module B
  def hello
    include A
    puts "hello"
    def goodbye
  end
        puts "B goodbye world"
end
      end
  end


module B
  module C
  def hello
    include A
    puts "hello world"
      def goodbye
  end
        puts "C goodbye world"
end
      end
  end


class C
Now consider a class D that inherits from B and C. This inheritance can be done in the following ways :-
  include B
  include A
  puts C.new.hello
end


Output: hello
Method 1:
nil


Now instead if we change the order of include in class C
  class D
      include A
      include B
  end


class C
or
  include A
  include B
  puts C.new.hello
end


Output: hello world
Method 2:
nil


  class D
      include B
      include A
  end


However, it is better to avoid such situations altogether. So even though it may seem viable in the above example, it may not be when multiple modules are included within a class.
Suppose an object of class D calls the goodbye method, an ambiguity arises in other multiple inheritance implementations as to which goodbye method to invoke, B.goodbye or C.goodbye. In Ruby, the output will depend on which module is included last and the method associated to the last module included will be invoked. In the above example, Method 1 will output "B goodbye world" and Method 2 will output "A goodbye world".


==Mixins vs interfaces==


Q2. Are mixins a clear advance over interfaces?
Multiple inheritance in Java is not existent. It prohibits a class from inheriting from multiple parent classes. Instead Java uses [http://en.wikipedia.org/wiki/Interface_(Java) interfaces] to avoid the ambiguity problem that arises with multiple inheritance.


Java does not use multiple inheritance. Instead it uses interfaces. Moreover in Java, each class can have only one parent. Also, functions declared within the interface cannot be implemented within that interface. An interface cannot have any member variables.
Interfaces are applied in Java by using the "implements" keyword. A subclass B can implement a parent class A and override the interfaced methods. Now in the parent class, the methods that are declared as interfaces must only be declared and do not contain a method definition. Also, interfaces do not have any private variables. A major disadvantage with this is that when a subclass implements a parent class, all the interfaces defined in the parent class must be reimplemented. Hence, the programming complexity and planning required to design interfaces is high.
However with a mixin, modules can include the implementation of the methods along with their definitions.


However with a mixin, all the method definitions are included within the module. Also there are no type components associated with mixins and hence no type abstraction is required. It cannot be said that mixins are clearly better than interfaces. Disadvantages in mixins such as namespace overpopulation serve a major hindrance to mixin implementation.


Q3. Do mixins have any disadvantages not shared by multiple inheritance or interfaces
=Disadvantages of Mixins=


Although mixins help solve the diamond problem, there is a disadvantage to it. If the method having the same as the modules which it includes, it implements the method in the class, without providing the user any warning.
Although mixins help solve the diamond problem, there is a disadvantage to it. If the method having the same as the modules which it includes, it implements the method in the class, without providing the user any warning.
Line 107: Line 111:
nil
nil


Pollution of the class namespace is another major disadvantage unique to mixins. As methods are imported from different modules, it is tough to keep track of the methods imported and it may be possible to override certain methods mistakenly. This [http://www.artima.com/weblogs/viewpost.jsp?thread=246341 article] talks about the limitations of mixins in greater detail.
=Conclusion=
Although mixins have certain advantages over multiple inheritance and interfaces, they also have their own share of disadvantages. If a lot of code reuse is desired and the programmer takes care to avoid the resulting ambiguity, then multiple inheritance can work well is such a situation. In places where multiple inheritance does not work, we can use interfaces or mixins. Depending on what the program requirements are one can choose from any of these three.
=References=
[http://en.wikipedia.org/wiki/Multiple_inheritance]  Multiple Inheritance
[http://en.wikipedia.org/wiki/Diamond_problem]      Diamond Problem


Conclusion:
[http://www.scala-lang.org/node/117] Mixins in Scala


Although mixins have certain advantages over multiple inheritance and interfaces, they also have their own share of disadvantages. So, we cannot say that mixins are indeed better.
[http://ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html]  Programming Ruby :The Pragmatic Programmer's Guide


[http://download.oracle.com/javase/tutorial/java/concepts/interface.html]    What is an interface?


References:
[http://www.cprogramming.com/tutorial/virtual_inheritance.html]    Virtual Inheritance
CSC 517 Lecture Notes
http://en.wikipedia.org/wiki/Multiple_inheritance
http://en.wikipedia.org/wiki/Diamond_problem
http://ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html
http://download.oracle.com/javase/tutorial/java/concepts/interface.html


Further reading:
[http://www.artima.com/weblogs/viewpost.jsp?thread=246341]      Mixins Considered Harmful
http://www.cprogramming.com/tutorial/virtual_inheritance.html

Latest revision as of 00:35, 16 October 2010

Multiple inheritance and mixins

Introduction

Multiple inheritance is often deemed as a very powerful tool in the Object Oriented Programming paradigm. Implementation of multiple inheritance in languages like Java (interfaces) and C++ is restricted and can often lead to a number of difficulties like the Diamond Problem, Virtual Inheritance issue and increase in programming complexity.

Mixins provide a way to mimic the functionality of multiple inheritance without inheriting the limitations of traditional multiple inheritance. Mixins can be found in languages like Python, Scala, Ruby etc.

Mixins

Mixins are a collection of methods that can be injected into a class without instantiation. It serves as a means of extending the functionality of the sub class. A class can inherit functionality from one or more mixins.

Here is an illustration of how mixins work in Ruby. Mixins are implemented as modules which contains various methods. In the following example, there are two modules, A and B.


Now consider a class C that inherits functionality from both the modules A and B. Here is an illustration of the structure of class C after the multiple inheritance from the two mixins.

As it is clearly shown in the above hierarchy, class C inherits the modules A and B by using the "include" keyword. Now when an object of C is created, A and B will not be instantiated since modules have not particular instantiation. This object will still access to all the methods of modules A and B along with the modules defined in the class C. This is different from multiple inheritance in C++ where when a subclass is instantiated, the parent classes get instantiated as well.

Mixins vs Other multiple inheritance

Runtime Extensions

Mixins allows the programmer to extend the functionality, add methods and change the behavior of core classes at runtime. This feature is extremely useful since these changes will not effect the way the objects are instantiated in the program. This makes writing plugins, extensions and other changes to the framework very easy. In frameworks written in other languages, such as Java, plugging in new functionality means that you need to change how your objects are instantiated. This will require code changes and/or potentially configuration changes

Diamond Problem

Earlier we had discussed the Diamond Problem and its impact on multiple inheritance. Here is how the scenario changes with the usage of mixins in Ruby. When ever any ambiguity arises with regard to method inheritance, the method that was included last is considered. Hence the need for virtual inheritance is alleviated.

This can be illustrated with the following example. Consider a module A in inherited by modules B and C.

  module A
     def goodbye
        puts "hello"
     end
  end
  module B
   include A  
    def goodbye
        puts "B goodbye world"
     end
  end
  module C
    include A
     def goodbye
        puts "C goodbye world"
     end
  end

Now consider a class D that inherits from B and C. This inheritance can be done in the following ways :-

Method 1:

  class D
     include A
     include B
  end 

or

Method 2:

  class D
     include B
     include A
  end

Suppose an object of class D calls the goodbye method, an ambiguity arises in other multiple inheritance implementations as to which goodbye method to invoke, B.goodbye or C.goodbye. In Ruby, the output will depend on which module is included last and the method associated to the last module included will be invoked. In the above example, Method 1 will output "B goodbye world" and Method 2 will output "A goodbye world".

Mixins vs interfaces

Multiple inheritance in Java is not existent. It prohibits a class from inheriting from multiple parent classes. Instead Java uses interfaces to avoid the ambiguity problem that arises with multiple inheritance.

Interfaces are applied in Java by using the "implements" keyword. A subclass B can implement a parent class A and override the interfaced methods. Now in the parent class, the methods that are declared as interfaces must only be declared and do not contain a method definition. Also, interfaces do not have any private variables. A major disadvantage with this is that when a subclass implements a parent class, all the interfaces defined in the parent class must be reimplemented. Hence, the programming complexity and planning required to design interfaces is high.

However with a mixin, all the method definitions are included within the module. Also there are no type components associated with mixins and hence no type abstraction is required. It cannot be said that mixins are clearly better than interfaces. Disadvantages in mixins such as namespace overpopulation serve a major hindrance to mixin implementation.

Disadvantages of Mixins

Although mixins help solve the diamond problem, there is a disadvantage to it. If the method having the same as the modules which it includes, it implements the method in the class, without providing the user any warning.

module A

 def hello
   puts "hello"
 end

end

module B

 def hello
   puts "hello world"
 end

end

class C

 include A
 include B
 def hello
   puts "this is the Hello from Class C"
 end
 puts C.new.hello

end

Output: this is the Hello from Class C nil

Pollution of the class namespace is another major disadvantage unique to mixins. As methods are imported from different modules, it is tough to keep track of the methods imported and it may be possible to override certain methods mistakenly. This article talks about the limitations of mixins in greater detail.

Conclusion

Although mixins have certain advantages over multiple inheritance and interfaces, they also have their own share of disadvantages. If a lot of code reuse is desired and the programmer takes care to avoid the resulting ambiguity, then multiple inheritance can work well is such a situation. In places where multiple inheritance does not work, we can use interfaces or mixins. Depending on what the program requirements are one can choose from any of these three.

References

[1] Multiple Inheritance

[2] Diamond Problem

[3] Mixins in Scala

[4] Programming Ruby :The Pragmatic Programmer's Guide

[5] What is an interface?

[6] Virtual Inheritance

[7] Mixins Considered Harmful