CSC/ECE 517 Fall 2011/ch1 2c bs: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(33 intermediate revisions by 2 users not shown)
Line 1: Line 1:
==Introduction:==
==Introduction==
An interface in the Java programming language is an abstract type that is used to specify an interface that classes must implement. Interface may only contain method signature and constant declarations. An interface may never contain method definitions. Interfaces cannot be instantiated. A class that implements an interface must implement all of the methods described in the interface, or be an abstract class. Object references in Java may be specified to be of an interface type; in which case, they must either be null, or be bound to an object that implements the interface.  
An [http://en.wikipedia.org/wiki/Interface_(computing) interface] in the [http://en.wikipedia.org/wiki/Java_(programming_language) Java] programming language is an abstract type that is used to specify an interface that classes must implement. Interface may only contain [http://en.wikipedia.org/wiki/Method_signature method signature] and constant declarations. An interface may never contain method definitions. Interfaces cannot be instantiated. A class that implements an interface must implement all of the methods described in the interface, or be an [http://en.wikipedia.org/wiki/Abstract_type abstract] class. Object references in Java may be specified to be of an interface type; in which case, they must either be null, or be bound to an object that implements the interface.  
In object-oriented programming languages, a mixin is a class that provides a certain functionality to be inherited or just reused by a subclass. Some of the functionality of mixins is provided by interfaces in popular languages like Java and C#. However, an interface only specifies what the class must support and cannot provide an implementation. Another class, providing an implementation and dependent with the interface, is needed for refactoring common behavior into a single place. Interfaces combined with aspect-oriented programming can produce full-fledged mixins in languages that support such features, such as C# or Java.  
 
One benefit of using interfaces is that they simulate multiple inheritance. All classes in Java other than java.lang.Object, must have exactly one base class; multiple inheritance of classes is not allowed.
In object-oriented programming languages, a [http://en.wikipedia.org/wiki/Mixin mixin] is a class that provides a certain functionality to be inherited or just reused by a subclass. Some of the functionality of mixins is provided by interfaces in popular languages like Java and [http://en.wikipedia.org/wiki/C_Sharp_(programming_language) C#]. However, an interface only specifies what the class must support and cannot provide an implementation. Another class, providing an implementation and dependent with the interface, is needed for refactoring common behavior into a single place. Interfaces combined with aspect-oriented programming can produce full-fledged mixins in languages that support such features, such as C# or Java.  
One benefit of using interfaces is that they simulate [http://en.wikipedia.org/wiki/Multiple_inheritance multiple inheritance]. All classes in Java other than [https://matrix.senecac.on.ca:8443/wiki/javaSE/index.php/Java.lang.Object java.lang.Object], must have exactly one base class; multiple inheritance of classes is not allowed.
 
==Overview==
==Overview==
===Mixins in Ruby===  
===Mixins in Ruby===  
In Java you just have classes (both abstract and concrete) and interfaces. The Ruby language provides classes, modules, and a mix of both. Inheriting from a mixin is not a form of specialization but is rather a means of collecting functionality. A class may inherit most or all of its functionality from one or more mixins through multiple inheritance. A mixin can also be viewed as an interface with implemented methods. When a class includes a mixin, the class implements the interface and includes, rather than inherits, all the mixins’ attributes (fields, properties) and methods. They become part of the class during compilation. A mixin can defer definition and binding of methods until runtime, though attributes and instantiation parameters are still defined at compile time. In the Ruby language a mixin is a class that is mixed with a module.  
In Java you just have [http://en.wikipedia.org/wiki/Class_(computer_programming) classes] (both abstract and concrete) and interfaces. The [http://en.wikipedia.org/wiki/Ruby Ruby] language provides classes,[http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html modules], and a mix of both. Inheriting from a mixin is not a form of specialization but is rather a means of collecting functionality. A class may inherit most or all of its functionality from one or more mixins through multiple inheritance. A mixin can also be viewed as an interface with implemented methods. When a class includes a mixin, the class implements the interface and includes, rather than inherits, all the mixins’ attributes (fields, properties) and methods. They become part of the class during compilation. A mixin can defer definition and binding of methods until runtime, though attributes and instantiation parameters are still defined at compile time. In the Ruby language a mixin is a class that is mixed with a module.  


====Module====
====Module====


A module is a degenerate abstract class. A module can’t be instantiated and no class can directly extend it but it can fully implement methods. A class can leverage the implementation of a module by including the module’s methods. A module can define methods that can be shared in different and separate classes either at the class or instance level.  
A [http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html module] is a degenerate abstract class. A module can’t be instantiated and no class can directly extend it but it can fully implement methods. A class can leverage the implementation of a module by including the module’s methods. A module can define methods that can be shared in different and separate classes either at the class or instance level. We can view an example module that converts a numeric value to its English word.


'''Example of Module:'''


   # Convert a integer value to English.
   # Convert a integer value to English.
Line 27: Line 28:
   end
   end


The Stringify module above makes use of a @value instance variable. The class that will be mixed with this module needs to define and set a @value instance variable since the Stringify module uses it but does not define it. In addition to instance variables a module could invoke methods not defined in the module but in the class that it will be mixed with.
The Stringify module above makes use of a @value [http://en.wikipedia.org/wiki/Instance_variable instance variable]. The class that will be mixed with this module needs to define and set a @value instance variable since the Stringify module uses it but does not define it. In addition to instance variables a module could invoke methods not defined in the module but in the class that it will be mixed with.




Line 41: Line 42:




The methods in the Math module are intended to be invoked like class methods, also known as static methods. The add method in the Math module accepts two integer values and returns an instance of BigInteger.
The methods in the Math module are intended to be invoked like class methods, also known as [http://en.wikipedia.org/wiki/Method_(computer_programming)#Static_methods static] methods. The add method in the Math module accepts two integer values and returns an [http://en.wikipedia.org/wiki/Instance_(computer_science) instance] of BigInteger.


====Using Mixins:====
====Using Mixins====


Implementation of the class and module are joined, intertwined, combined, etc. A mixin is a different mechanism to the extend construct used to add concrete implementation to a class. With a mixin you can extend from a module instead of a class.  
Implementation of the class and module are joined, interwined, combined, etc. A mixin is a different mechanism to the extend construct used to add concrete implementation to a class. With a mixin you can extend from a module instead of a class.  


This is the implementation of BigInteger class. The BigInteger class defines one constructor and directly inherits one method from the Number base class. To mix in the methods implemented in the Stringify and Math modules with the BigInteger class you will note the usage of the include and extend methods, respectively.
This is the implementation of BigInteger class. The BigInteger class defines one constructor and directly inherits one method from the Number base class. To mix in the methods implemented in the Stringify and Math modules with the BigInteger class you will note the usage of the include and extend methods, respectively.
Line 109: Line 110:
   puts bigint1.format  # will generate an error
   puts bigint1.format  # will generate an error


Modules that will be mixed with a class via the include or extend method could define something like a contructor or initializer method to the module. The module initializer method will be invoked at the time the module is mixed with a class. When a class extends a module the module’s self.extended method will be invoked:
Modules that will be mixed with a class via the include or extend method could define something like a constructor or initializer method to the module. The module initializer method will be invoked at the time the module is mixed with a class. When a class extends a module the module’s self.extended method will be invoked:


   module Math
   module Math
Line 194: Line 195:




===Mixins vs Interfaces===
==Mixins vs Interfaces==
Because of this mixin feature, a developer can add arbitrary methods and modify behavior of core classes at runtime. This is amazingly powerful if you are trying to write plugins and extensions to the framework.  Because you can add functionality to existing objects, users can install your plugin and start taking advantage of new functionality without having to make changes to the objects that they are instantiating in their application.  
Because of this mixin feature, a developer can add arbitrary methods and modify behavior of core classes at runtime. This is amazingly powerful if you are trying to write plugins and extensions to the [http://en.wikipedia.org/wiki/Software_framework framework].  Because you can add functionality to existing objects, users can install their [http://en.wikipedia.org/wiki/Plug-in_(computing) plugin] and start taking advantage of new functionality without having to make changes to the objects that they are instantiating in their application.  


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 which makes it hard to develop, hard to maintain, and a pain for plugin developers to support.  But because of the mixin feature, Rails plugin developers can customize the base objects and the users of the plugins do not have to change any of their code or configuration logic.
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 which makes it hard to develop, hard to maintain, and a pain for plugin developers to support.  But because of the mixin feature, Rails plugin developers can customize the base objects and the users of the plugins do not have to change any of their code or configuration logic.


• Use include or extend keywords in ruby to include the module methods in the ruby class.
===Differences===
Use implement keyword in java to be able to implement the methods of interface.


• No need to implement the methods which are included in ruby
These is a general comparision:
Need to implement all the methods of the interface class in the class.


The methods are not copied into the class in which they are included, rather they are referenced.
{| class="wikitable"
The methods’ implementation is present in the class itself.
|-
! Mixins in Ruby
• All the classes which include the function have the same functionality.
! Interfaces in Java
Every class which implements the interface may have different functionality.
|-
| 'include' or 'extend' keywords used to include the module in the class.
| 'implement' keyword is used to implement interface
 
|-
| Need not implement the module methods in the class.
| Should implement the interface methods.
 
|-
| The methods are not copied into the class in which they are included. They are referenced.
| The methods’ implementation is in the class itself.


The included method definition is decided at ‘run time’. If the definition changes while running the function points to the changed code.  
|-
The definition is known compile time and will not change until the code is compiled and run again.  
| The included method definition is decided at ‘run time’. If the definition changes while running the function points to the changed code.
| The definition is known compile time and will not change until the code is compiled and run again.  


Modules inclusion does not provide a superclass and subclass relationship  
|-
Interface extending provides a superclass and subclass relationship.
| Modules inclusion does not provide a superclass and subclass relationship.
| Interface extending provides a superclass and subclass relationship.  


When we use mixins we included only a module of the class.
|-
We include the entire interface class.
| When we use mixins we included only a module of the class.  
| We include the entire interface class.  


Mainly for code reuse and does not provide any hierarchy.
|-
It provides a hierarchy.
| Mainly for code reuse and does not provide any hierarchy.  
| It provides a hierarchy.  


|}


===Functionality and Behavior Comparison===
The functionality and behavior of Mixins in Ruby is compared with Interfaces in Java


1. Comparable Functionality
====Comparable Functionality====
Sometime we are required to compare the class members of different objects of the same class and/or sort them. This is the comparable functionality that we are trying to achieve for a given class.  This functionality can be achieved by both the Ruby using mixins and Java using interfaces. There is not much difference using both.
Sometime we are required to compare the class members of different objects of the same class and/or sort them. This is the comparable functionality that we are trying to achieve for a given class.  This functionality can be achieved by both the Ruby using mixins and Java using interfaces. There is not much difference using both.


a. Ruby
'''Ruby'''
The Comparable mixin is used by classes whose objects may be ordered. The class must define the <=> operator, which compares the receiver against another object, returning -1, 0, or +1 depending on whether the receiver is less than, equal to, or greater than the other object. Comparable uses <=> to implement the conventional comparison operators (<, <=, ==, >=, and >) and the method between?.
 
The [http://www.ruby-doc.org/core/classes/Comparable.html Comparable] mixin is used by classes whose objects may be ordered. The class must define the <=> operator, which compares the receiver against another object, returning -1, 0, or +1 depending on whether the receiver is less than, equal to, or greater than the other object. Comparable uses <=> to implement the conventional comparison operators (<, <=, ==, >=, and >) and the method between?.


class SizeMatters
  class SizeMatters
     include Comparable
     include Comparable
     attr :str
     attr :str
Line 244: Line 261:
     end
     end
   end
   end
''using class:''


   s1 = SizeMatters.new("Z")
   s1 = SizeMatters.new("Z")
Line 251: Line 270:
   s5 = SizeMatters.new("VVVVV")
   s5 = SizeMatters.new("VVVVV")


''output:''
   s1 < s2                      #=> true
   s1 < s2                      #=> true
   s4.between?(s1, s3)          #=> false
   s4.between?(s1, s3)          #=> false
Line 257: Line 277:




'''Java'''


 
In Java, comparable functionality is achieved by extending the “Comparable” interface. List of objects that implement this interface can be sorted automatically by sort method of the list interface. This interface has compareTo() method that is used by the sort() method of the list. Here compareTo() method can also be used to compare two objects with respect to the implementation in compareTo() implementation in the derived class. It returns ‘0’ , ‘1’ and ‘-1’ corresponding to whether one is equal to , greater than or lesser than other.
 
b. Java
In java comparable functionality is achieved by extending the “Comparable” interface. List of objects that implement this interface can be sorted automatically by sort method of the list interface. This interface has compareTo() method that is used by the sort() method of the list. Here compareTo() method can also be used to compare two objects with respect to the implementation in compareTo() implementation in the derived class. It returns ‘0’ , ‘1’ and ‘-1’ corresponding to whether one is equal to , greater than or lesser than other.
In this example code Employee class is implementing Comparable interface and have method compareTo().
In this example code Employee class is implementing Comparable interface and have method compareTo().
public class Employee implements Comparable {
  public class Employee implements Comparable {
 
     int EmpID;
     int EmpID;
     String Ename;
     String Ename;
     double Sal;
     double Sal;
     static int i;
     static int i;
     public Employee() {
     public Employee() {
         EmpID = i++;
         EmpID = i++;
Line 275: Line 291:
         Sal = 0.0;
         Sal = 0.0;
     }
     }
     public Employee(String ename, double sal) {
     public Employee(String ename, double sal) {
         EmpID = i++;
         EmpID = i++;
Line 281: Line 296:
         Sal = sal;
         Sal = sal;
     }
     }
     public String toString() {
     public String toString() {
         return "EmpID " + EmpID + "\n" + "Ename " + Ename + "\n" + "Sal" + Sal;
         return "EmpID " + EmpID + "\n" + "Ename " + Ename + "\n" + "Sal" + Sal;
     }
     }
     public int compareTo(Object o1) {
     public int compareTo(Object o1) {
         if (this.Sal == ((Employee) o1).Sal)
         if (this.Sal == ((Employee) o1).Sal)
Line 294: Line 307:
             return -1;
             return -1;
     }
     }
}
  }
 
ComparableDemo.java is showing the use of this interface. This class first makes a list of objects of type Employee and call sort method of java.util.Collections, which internally uses compareTo() method of Employee class and sort the list accordingly.
import java.util.*;
 
public class ComparableDemo{


ComparableDemo.java is showing the use of this interface. This class first makes a list of objects of type Employee and call sort method of java.util.Collections, which internally uses compareTo() method of Employee class and sort the list accordingly.
  import java.util.*;
  public class ComparableDemo{
     public static void main(String[] args) {
     public static void main(String[] args) {
         List ts1 = new ArrayList();
         List ts1 = new ArrayList();
         ts1.add(new Employee ("Tom",40000.00));
         ts1.add(new Employee ("Tom",40000.00));
Line 310: Line 321:
         Collections.sort(ts1);
         Collections.sort(ts1);
         Iterator itr = ts1.iterator();
         Iterator itr = ts1.iterator();
         while(itr.hasNext()){
         while(itr.hasNext()){
             Object element = itr.next();
             Object element = itr.next();
             System.out.println(element + "\n");
             System.out.println(element + "\n");  
           
         }
         }
     }
     }
}
}
Output:
EmpID 1
Ename Harry
Sal20000.0
EmpID 0
Ename Tom
Sal40000.0
EmpID 2
Ename Maggie
Sal50000.0
EmpID 3
Ename Chris
Sal70000.0


''Output:''
 
  EmpID 1
  Ename Harry
  Sal    20000.0
  EmpID 0
  Ename Tom
  Sal    40000.0
  EmpID 2
  Ename Maggie
  Sal    50000.0
  EmpID 3
  Ename Chris
  Sal    70000.0


2. Singleton
====Singleton Behaviour====


A Singleton is a class guaranteed to have only a single instance, with a single global access point to that instance. It can be implemented in Ruby and Java. In Ruby we can include a module to acquire all the functionality of the singleton module. The code is already there and we are just reusing the code and adding that similar functionality into our class. Here our intention is to add the functionality of singleton to the class which is achieved using mixins. In java, implementation of interfaces means that the class which implements the interface becomes a type of that class, which is not the intention here. So, there is not interface which class can implement to get the functionality in itself. It has to implement the functionality itself without implementing any interface.  
A [http://en.wikipedia.org/wiki/Singleton_pattern Singleton] is a class guaranteed to have only a single instance, with a single global access point to that instance. It can be implemented in Ruby and Java. In Ruby we can include a module to acquire all the functionality of the singleton module. The code is already there and we are just reusing the code and adding that similar functionality into our class. Here our intention is to add the functionality of singleton to the class which is achieved using mixins. In java, implementation of interfaces means that the class which implements the interface becomes a type of that class, which is not the intention here. So, there is not interface which class can implement to get the functionality in itself. It has to implement the functionality itself without implementing any interface.  


'''Ruby'''


Ruby
When you include the singleton method inside your class it makes the new method private so that you cannot use it. Including ‘singleton’ adds a class method called instance that instantiates only one instance of the class
When you include the singleton method inside your class it makes the new method private so that you cannot use it. Including ‘singleton’ adds a class method called instance that instantiates only one instance of the class


# require singleton lib
  # require singleton lib
require 'singleton'
  require 'singleton'
class AppConfig
  class AppConfig
  # mixin the singleton module
    # mixin the singleton module
  include Singleton
    include Singleton
  # do the actual app configuration
    # do the actual app configuration
  def load_config(file)
    def load_config(file)
    # do your work here
      # do your work here
    puts "Application configuration file was loaded from file: #{file}"
      puts "Application configuration file was loaded from file: #{file}"
    end
   end
   end
end


conf1 = AppConfig.instance
''output:''
conf1.load_config "/home/khelll/conf.yml"
#=>Application configuration file was loaded from file: /home/khelll/conf.yml
conf2 = AppConfig.instance
puts conf1 == conf2
#=>true
# notice the following 2 lines won’t work
AppConfig.new rescue(puts $!)
#=> new method is private


  conf1 = AppConfig.instance
  conf1.load_config "/home/khelll/conf.yml"      #=>Application configuration file was loaded from file: /home/khelll/conf.yml
  conf2 = AppConfig.instance
  puts conf1 == conf2      #=>true
  # notice the following 2 lines won’t work
  AppConfig.new rescue(puts $!)  #=> new method is private


3. Enumerable
====Enumerable Behaviour====
This enumerable functionality adds support to the array members of the class. We can achieve this functionality using mixins in Ruby while it is not possible to do it in Java using interfaces.
This [http://www.ruby-doc.org/core/classes/Enumerable.html enumerable] functionality adds support to the array members of the class. We can achieve this functionality using mixins in Ruby while it is not possible to do it in Java using interfaces.
 
'''Implementation in Ruby:'''


Implementation in Ruby:
It adds the functionality of map, inject, select etc to the class which includes the ‘Enumerable’ module. The class which includes should represent a collection of items. Enumerable requires that your class contain an each method that serves up the items in the collection. All the other Enumerable methods rely on this.  
It adds the functionality of map, inject, select etc to the class which includes the ‘Enumerable’ module. The class which includes should represent a collection of items. Enumerable requires that your class contain an each method that serves up the items in the collection. All the other Enumerable methods rely on this.  
Example:
Example:
This is a Team class that manages a group of members:
This is a Team class that manages a group of members:


class Team
  class Team
  include Enumerable
    include Enumerable
    attr_accessor :members
    def initialize
      @members = []
    end
    def each &block
      @members.each{|member| block.call(member)}
    end
  end


  attr_accessor :members
Enumerable requires that your class contain an each method that serves up the items in the collection. All the other Enumerablemethods rely on this. Now we can use the map method, for instance:


   def initialize
   team = Team.new
    @members = []
  team.members = ['joshua', 'gabriel', 'jacob']
   end
   team.map{|member| member.capitalize}  # => ["Joshua", "Gabriel", "Jacob"]


  def each &block
Now we can call any Enumerable methods on our team object itself, and it will assume we want to work with the members array within.
    @members.each{|member| block.call(member)}
  end
end


Enumerable requires that your class contain an each method that serves up the items in the collection. All the other Enumerablemethods rely on this. Now we can use the map method, for instance:
team = Team.new
team.members = ['joshua', 'gabriel', 'jacob']
team.map{|member| member.capitalize}  # => ["Joshua", "Gabriel", "Jacob"]


Now we can call any Enumerable methods on our team object itself, and it will assume we want to work with the members array within.
====Data Mapper====


4. Data Mapper
[http://datamapper.org/docs/ DataMapper] is an API which comes with the ability to use the same API to talk to a multitude of different datastores. There are adapters for the usual RDBMS suspects, NoSQL stores, various file formats and even some popular webservices. This is implemented in ruby using mixins. We need not use interfaces to implement.
DataMapper is an API which comes with the ability to use the same API to talk to a multitude of different datastores. There are adapters for the usual RDBMS suspects, NoSQL stores, various file formats and even some popular webservices. This is implemented in ruby using mixins. We need not use interfaces to implement.


Implementation in Ruby:
'''Implementation in Ruby:'''
class Post
  class Post
       include DataMapper::Resource
       include DataMapper::Resource
       property :id, Serial
       property :id, Serial
end
  end
 
==Conclusion==
The point to take away from this is not that Ruby Mixins are more powerful than Java Interfaces. The mixin feature of Ruby allows for the development of easy to use but powerful plugins that will be hard for any non-Ruby based framework to compete with. Java has many other ways of implementing the functionality mixins are capable of. It is just that it does not use Interfaces to achieve the functionality. Even though both of them are a way of achieving multiple inheritance in their respective languages, they achieve quiet different goals. Inheritance in Java is mainly to overcome the confusion which arises with multiple inheritance, while Mixins in Ruby is mainly to add an additional functionality to the existing class apart from the ‘primary functionality’ of the class.


Conclusion
The point to take away from this is not that Ruby Mixins are more powerful than Java Interfaces. The mixin feature of Ruby allows for the development of easy to use but powerful plugins that will be hard for any non-Ruby based framework to compete with. Java has many other ways of implementing the functionalities mixins are capable of. It is just that it does not use Interfaces to achieve the functionality. Even though both of them are a way of achieving multiple inheritance in their respective languages, they achieve quiet different goals. Inheritance in Java is mainly to overcome the confusion which arises with multiple inheritance, while Mixins in Ruby is mainly to add an additional functionality to the existing class apart from the ‘primary functionality’ of the class.
When a class implements Interface, it indicates that it is of the type interface class and forms a hierarchy with the interface class, while ruby mixins are mainly intended for code reuse and including an additional functionality to the class. It does not form any hierarchy as it is only using module of the class.  
When a class implements Interface, it indicates that it is of the type interface class and forms a hierarchy with the interface class, while ruby mixins are mainly intended for code reuse and including an additional functionality to the class. It does not form any hierarchy as it is only using module of the class.  


References
==References==
* http://en.wikipedia.org/wiki/Mixin
* http://en.wikipedia.org/wiki/Interface_(Java)
* http://carboni.ca/blog/p/Modules-How-Do-They-Work
* http://rubylearning.com/satishtalim/modules_mixins.html
* http://www.innovationontherun.com/why-rubys-mixins-gives-rails-an-advantage-over-java-
* http://datamapper.org/
* http://www.dsource.org/projects/tutorials/wiki/SingletonPattern
* http://corelib.rubyonrails.org/classes/Comparable.html
* http://kconrails.com/2010/11/30/ruby-enumerable-primer-part-1-the-basics/
* http://stackoverflow.com/questions/575920/is-a-ruby-module-equivalent-to-a-java-interface

Latest revision as of 00:23, 23 September 2011

Introduction

An interface in the Java programming language is an abstract type that is used to specify an interface that classes must implement. Interface may only contain method signature and constant declarations. An interface may never contain method definitions. Interfaces cannot be instantiated. A class that implements an interface must implement all of the methods described in the interface, or be an abstract class. Object references in Java may be specified to be of an interface type; in which case, they must either be null, or be bound to an object that implements the interface.

In object-oriented programming languages, a mixin is a class that provides a certain functionality to be inherited or just reused by a subclass. Some of the functionality of mixins is provided by interfaces in popular languages like Java and C#. However, an interface only specifies what the class must support and cannot provide an implementation. Another class, providing an implementation and dependent with the interface, is needed for refactoring common behavior into a single place. Interfaces combined with aspect-oriented programming can produce full-fledged mixins in languages that support such features, such as C# or Java. One benefit of using interfaces is that they simulate multiple inheritance. All classes in Java other than java.lang.Object, must have exactly one base class; multiple inheritance of classes is not allowed.

Overview

Mixins in Ruby

In Java you just have classes (both abstract and concrete) and interfaces. The Ruby language provides classes,modules, and a mix of both. Inheriting from a mixin is not a form of specialization but is rather a means of collecting functionality. A class may inherit most or all of its functionality from one or more mixins through multiple inheritance. A mixin can also be viewed as an interface with implemented methods. When a class includes a mixin, the class implements the interface and includes, rather than inherits, all the mixins’ attributes (fields, properties) and methods. They become part of the class during compilation. A mixin can defer definition and binding of methods until runtime, though attributes and instantiation parameters are still defined at compile time. In the Ruby language a mixin is a class that is mixed with a module.

Module

A module is a degenerate abstract class. A module can’t be instantiated and no class can directly extend it but it can fully implement methods. A class can leverage the implementation of a module by including the module’s methods. A module can define methods that can be shared in different and separate classes either at the class or instance level. We can view an example module that converts a numeric value to its English word.


 # Convert a integer value to English.
 module Stringify
   # Requires an instance variable @value
   def stringify
     if @value == 1
       "One"
     elsif @value == 2
       "Two"
     elsif @value == 3
       "Three"
     end
   end
 end

The Stringify module above makes use of a @value instance variable. The class that will be mixed with this module needs to define and set a @value instance variable since the Stringify module uses it but does not define it. In addition to instance variables a module could invoke methods not defined in the module but in the class that it will be mixed with.


Self Contained Module:

 # A Math module akin to Java Math class.
 module Math
   # Could be called as a class, static, method
   def add(val_one, val_two)
     BigInteger.new(val_one + val_two)
   end
 end


The methods in the Math module are intended to be invoked like class methods, also known as static methods. The add method in the Math module accepts two integer values and returns an instance of BigInteger.

Using Mixins

Implementation of the class and module are joined, interwined, combined, etc. A mixin is a different mechanism to the extend construct used to add concrete implementation to a class. With a mixin you can extend from a module instead of a class.

This is the implementation of BigInteger class. The BigInteger class defines one constructor and directly inherits one method from the Number base class. To mix in the methods implemented in the Stringify and Math modules with the BigInteger class you will note the usage of the include and extend methods, respectively.

 # Base Number class
 class Number
   def intValue
     @value
   end
 end

 # BigInteger extends Number
 class BigInteger < Number

 # Add instance methods from Stringify
 include Stringify

 # Add class methods from Math
 extend Math

 # Add a constructor with one parameter
   def initialize(value)
     @value = value
   end
 end

Using the class:

 # Create a new object
 bigint1 = BigInteger.new(10)
 # Call a method inherited from the base class
 puts bigint1.intValue   # --> 10

The extend method will mix a module’s methods at the class level. The method defined in the Math module can be used as a class/static method.

 # Call class method extended from Math
 bigint2 = BigInteger.add(-2, 4)
 puts bigint2.intValue   # --> 2

The include method will mix a module’s methods at the instance level, meaning that the methods will become instance methods. The method defined in the Stringify module can be used as an instance method.

 # Call a method included from Stringify
 puts bigint2.stringify   # --> 'Two'

There is another use of the extend method. You can enhance an object instance by mixing it with a module at run time. This ‘CurrencyFormatter’ is used to extend an object, changing it’s responsibilities at runtime.

 # Format a numeric value as a currency
 module CurrencyFormatter
   def format
     "$#{@value}"
   end
end

To mix an object instance with a module you can do the following:

 # Add the module methods to
 # this object instance, only!
 bigint2.extend CurrencyFormatter
 puts bigint2.format   # --> '$2'

Calling the extend method on an instance will only extend that one object; objects of the same class will not be extended with the new functionality.

 puts bigint1.format   # will generate an error

Modules that will be mixed with a class via the include or extend method could define something like a constructor or initializer method to the module. The module initializer method will be invoked at the time the module is mixed with a class. When a class extends a module the module’s self.extended method will be invoked:

 module Math
   def self.extended(base)
     # Initialize module.
   end
end

The self prefix indicates that the method is a static module level method. The base parameter in the static extended method will be either an instance object or class object of the class that extended the module depending whether you extend a object or class, respectively. When a class includes a module the module’s self.included method will be invoked.

 module Stringify
   def self.included(base)
     # Initialize module.
   end
 end

The base parameter will be a class object for the class that includes the module. It is important to note that inside the included and extended initializer methods you can include and extend other modules.

 module Stringify
   def self.included(base)
     base.extend SomeOtherModule
   end
 end

Interfaces in Java

Interfaces define a standardized set of commands that a class will obey. The commands are a set of methods that a class implements. The interface definition states the names of the methods and their return types and argument signatures. There is no executable body for any method. Example:

 interface Bicycle {
      void changeCadence(int newValue);   // wheel revolutions per minute
      void changeGear(int newValue);
      void speedUp(int increment);
      void applyBrakes(int decrement);
 }

Implementation is independent to each class that implements the interface. Once a class implements an interface, the Java compiler knows that an instance of the class will contain the specified set of methods. Therefore, it will allow you to call those methods for an object referenced by a variable whose type is the interface. Implementing an interface enables a class to be "plugged in" in any situation that requires a specific behavior (manifested through the set of methods).

 class ACMEBicycle implements Bicycle {
   //implementation specific to this class
      int cadence = 0;
      int speed = 0;
      int gear = 1;
      void changeCadence(int newValue) {
           cadence = newValue;
      }
      void changeGear(int newValue) {
           gear = newValue;
      }
      void speedUp(int increment) {
           speed = speed + increment;   
      }
      void applyBrakes(int decrement) {
           speed = speed - decrement;
      }
      void printStates() {
           System.out.println("cadence:"+cadence+" speed:"+speed+" gear:"+gear);
      }
  }
 class MOUNTAINBicycle implements Bicycle {
 int cadence = 2;
      int speed = 3;
      int gear = 5;
      void changeCadence(int newValue) {
           cadence = newValue + 10;
      }
      void changeGear(int newValue) {
           gear = newValue + 4;
      }
      void speedUp(int increment) {
           speed = speed + increment + 10;   
      }
      void applyBrakes(int decrement) {
           speed = speed – decrement – 10;
      }
      void printStates() {
           System.out.println("cadence:"+cadence+" speed:"+speed+" gear:"+gear);
      }
 }

Using an interface rather than inheritance to specify a certain set of methods allows a class to inherit from some other class. In other words, if a class needs two different sets of methods, so it can behave like two different types of things, it could inherit one set from class A, and use an interface B to specify the other. You could then reference one of these objects with either an A reference or a B reference. Implementing an interface allows a class to become more formal about the behavior it promises to provide. Interfaces form a contract between the class and the outside world, and this contract is enforced at build time by the compiler. If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile.


Mixins vs Interfaces

Because of this mixin feature, a developer can add arbitrary methods and modify behavior of core classes at runtime. This is amazingly powerful if you are trying to write plugins and extensions to the framework. Because you can add functionality to existing objects, users can install their plugin and start taking advantage of new functionality without having to make changes to the objects that they are instantiating in their application.

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 which makes it hard to develop, hard to maintain, and a pain for plugin developers to support. But because of the mixin feature, Rails plugin developers can customize the base objects and the users of the plugins do not have to change any of their code or configuration logic.

Differences

These is a general comparision:

Mixins in Ruby Interfaces in Java
'include' or 'extend' keywords used to include the module in the class. 'implement' keyword is used to implement interface
Need not implement the module methods in the class. Should implement the interface methods.
The methods are not copied into the class in which they are included. They are referenced. The methods’ implementation is in the class itself.
The included method definition is decided at ‘run time’. If the definition changes while running the function points to the changed code. The definition is known compile time and will not change until the code is compiled and run again.
Modules inclusion does not provide a superclass and subclass relationship. Interface extending provides a superclass and subclass relationship.
When we use mixins we included only a module of the class. We include the entire interface class.
Mainly for code reuse and does not provide any hierarchy. It provides a hierarchy.

Functionality and Behavior Comparison

The functionality and behavior of Mixins in Ruby is compared with Interfaces in Java

Comparable Functionality

Sometime we are required to compare the class members of different objects of the same class and/or sort them. This is the comparable functionality that we are trying to achieve for a given class. This functionality can be achieved by both the Ruby using mixins and Java using interfaces. There is not much difference using both.

Ruby

The Comparable mixin is used by classes whose objects may be ordered. The class must define the <=> operator, which compares the receiver against another object, returning -1, 0, or +1 depending on whether the receiver is less than, equal to, or greater than the other object. Comparable uses <=> to implement the conventional comparison operators (<, <=, ==, >=, and >) and the method between?.

 class SizeMatters
    include Comparable
    attr :str
    def <=>(anOther)
      str.size <=> anOther.str.size
    end
    def initialize(str)
      @str = str
    end
    def inspect
      @str
    end
  end

using class:

  s1 = SizeMatters.new("Z")
  s2 = SizeMatters.new("YY")
  s3 = SizeMatters.new("XXX")
  s4 = SizeMatters.new("WWWW")
  s5 = SizeMatters.new("VVVVV")

output:

  s1 < s2                       #=> true
  s4.between?(s1, s3)           #=> false
  s4.between?(s3, s5)           #=> true
  [ s3, s2, s5, s4, s1 ].sort   #=> [Z, YY, XXX, WWWW, VVVVV]


Java

In Java, comparable functionality is achieved by extending the “Comparable” interface. List of objects that implement this interface can be sorted automatically by sort method of the list interface. This interface has compareTo() method that is used by the sort() method of the list. Here compareTo() method can also be used to compare two objects with respect to the implementation in compareTo() implementation in the derived class. It returns ‘0’ , ‘1’ and ‘-1’ corresponding to whether one is equal to , greater than or lesser than other. In this example code Employee class is implementing Comparable interface and have method compareTo().

 public class Employee implements Comparable {
   int EmpID;
   String Ename;
   double Sal;
   static int i;
   public Employee() {
       EmpID = i++;
       Ename = "dont know";
       Sal = 0.0;
   }
   public Employee(String ename, double sal) {
       EmpID = i++;
       Ename = ename;
       Sal = sal;
   }
   public String toString() {
       return "EmpID " + EmpID + "\n" + "Ename " + Ename + "\n" + "Sal" + Sal;
   }
   public int compareTo(Object o1) {
       if (this.Sal == ((Employee) o1).Sal)
           return 0;
       else if ((this.Sal) > ((Employee) o1).Sal)
           return 1;
       else
           return -1;
   }
 }

ComparableDemo.java is showing the use of this interface. This class first makes a list of objects of type Employee and call sort method of java.util.Collections, which internally uses compareTo() method of Employee class and sort the list accordingly.

 import java.util.*;
 public class ComparableDemo{
   public static void main(String[] args) {
       List ts1 = new ArrayList();
       ts1.add(new Employee ("Tom",40000.00));
       ts1.add(new Employee ("Harry",20000.00));
       ts1.add(new Employee ("Maggie",50000.00));
       ts1.add(new Employee ("Chris",70000.00));
       Collections.sort(ts1);
       Iterator itr = ts1.iterator();
       while(itr.hasNext()){
           Object element = itr.next();
           System.out.println(element + "\n");   
       }
   }

}

Output:

 EmpID 1
 Ename Harry
 Sal    20000.0
 EmpID 0
 Ename Tom
 Sal    40000.0
 EmpID 2
 Ename Maggie
 Sal    50000.0
 EmpID 3
 Ename Chris
 Sal    70000.0

Singleton Behaviour

A Singleton is a class guaranteed to have only a single instance, with a single global access point to that instance. It can be implemented in Ruby and Java. In Ruby we can include a module to acquire all the functionality of the singleton module. The code is already there and we are just reusing the code and adding that similar functionality into our class. Here our intention is to add the functionality of singleton to the class which is achieved using mixins. In java, implementation of interfaces means that the class which implements the interface becomes a type of that class, which is not the intention here. So, there is not interface which class can implement to get the functionality in itself. It has to implement the functionality itself without implementing any interface.

Ruby

When you include the singleton method inside your class it makes the new method private so that you cannot use it. Including ‘singleton’ adds a class method called instance that instantiates only one instance of the class

 # require singleton lib
 require 'singleton'
 class AppConfig
   # mixin the singleton module
   include Singleton
   # do the actual app configuration
   def load_config(file)
     # do your work here
     puts "Application configuration file was loaded from file: #{file}"
   end
 end

output:

 conf1 = AppConfig.instance
 conf1.load_config "/home/khelll/conf.yml"       #=>Application configuration file was loaded from file: /home/khelll/conf.yml
 conf2 = AppConfig.instance
 puts conf1 == conf2      #=>true
 # notice the following 2 lines won’t work
 AppConfig.new rescue(puts $!)   #=> new method is private

Enumerable Behaviour

This enumerable functionality adds support to the array members of the class. We can achieve this functionality using mixins in Ruby while it is not possible to do it in Java using interfaces.

Implementation in Ruby:

It adds the functionality of map, inject, select etc to the class which includes the ‘Enumerable’ module. The class which includes should represent a collection of items. Enumerable requires that your class contain an each method that serves up the items in the collection. All the other Enumerable methods rely on this. Example: This is a Team class that manages a group of members:

 class Team
   include Enumerable
   attr_accessor :members
   def initialize
     @members = []
   end
   def each &block
     @members.each{|member| block.call(member)}
   end
 end

Enumerable requires that your class contain an each method that serves up the items in the collection. All the other Enumerablemethods rely on this. Now we can use the map method, for instance:

 team = Team.new
 team.members = ['joshua', 'gabriel', 'jacob']
 team.map{|member| member.capitalize}   # => ["Joshua", "Gabriel", "Jacob"]

Now we can call any Enumerable methods on our team object itself, and it will assume we want to work with the members array within.


Data Mapper

DataMapper is an API which comes with the ability to use the same API to talk to a multitude of different datastores. There are adapters for the usual RDBMS suspects, NoSQL stores, various file formats and even some popular webservices. This is implemented in ruby using mixins. We need not use interfaces to implement.

Implementation in Ruby:

 class Post
      include DataMapper::Resource
      property :id, Serial
 end

Conclusion

The point to take away from this is not that Ruby Mixins are more powerful than Java Interfaces. The mixin feature of Ruby allows for the development of easy to use but powerful plugins that will be hard for any non-Ruby based framework to compete with. Java has many other ways of implementing the functionality mixins are capable of. It is just that it does not use Interfaces to achieve the functionality. Even though both of them are a way of achieving multiple inheritance in their respective languages, they achieve quiet different goals. Inheritance in Java is mainly to overcome the confusion which arises with multiple inheritance, while Mixins in Ruby is mainly to add an additional functionality to the existing class apart from the ‘primary functionality’ of the class.

When a class implements Interface, it indicates that it is of the type interface class and forms a hierarchy with the interface class, while ruby mixins are mainly intended for code reuse and including an additional functionality to the class. It does not form any hierarchy as it is only using module of the class.

References