CSC/ECE 517 Fall 2011/ch2 2c ac: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(96 intermediate revisions by 2 users not shown)
Line 8: Line 8:
The article also tries to remark situations where the use of one mechanism would be more appropriate than the other.
The article also tries to remark situations where the use of one mechanism would be more appropriate than the other.


= Ruby mixins =
= Ruby [http://en.wikipedia.org/wiki/Mixin mixins] =
In Ruby a mixin happens when a <tt>module</tt> is included/mixed into a class or into another module.
In Ruby a mixin happens when a <tt>module</tt> is included/mixed into a class or into another module.


A <tt>module</tt> is "a way of groping together methods, classes and constants." (Thomas 76)
A <tt>module</tt> is "a way of grouping together" different elements like class/instance methods, classes, instance variables and constants.(Thomas [3] page 76)
Not only can modules contain class methods; they can also contain instance methods. (From lecture 6 note)


<pre>
<pre>
Line 22: Line 21:
end
end
</pre>
</pre>
A module cannot be instanciated but it can be included/mixed into another class that inherits anything that the module defines.
A module cannot be instantiated but it can be included/mixed into another class
<pre>
<pre>
# The Animal and the Car classes include/mix in the module Introspect
# The Animal and the Car classes include/mix in the module Introspect
Line 47: Line 46:
</pre>
</pre>


Notice that the code in the module has access to variables of the host class. In this sample the ''kind'' method defined in the ''Introspect''module accesses the <tt>self</tt> variable of the host class (either ''Animal'' or ''Car'').
Notice that the code in the module has access to variables of the host class. In this sample the ''kind'' method defined in the ''Introspect'' module accesses the <tt>self</tt> variable of the host class (either ''Animal'' or ''Car'').
 
Also notice that the <tt>include</tt> “statement makes a reference to a module. If multiple classes include that module they’ll all point to the same thing. If you change the definition of a method within that module, even while your program is running, all classes that include the module will exhibit the new behavior.” (Thomas 79)


=Java [http://download.oracle.com/javase/tutorial/java/concepts/interface.html interfaces]=
=Java [http://download.oracle.com/javase/tutorial/java/concepts/interface.html interfaces]=
Line 56: Line 53:
<pre>
<pre>
interface Bicycle {
interface Bicycle {
      void changeCadence(int newValue);  // wheel revolutions per minute


       void changeGear(int newValue);
       void changeGear(int newValue);
Line 70: Line 65:
class ACMEBicycle implements Bicycle {
class ACMEBicycle implements Bicycle {


  // remainder of this class implemented as before
    void changeGear(int newValue){
    // method implementation
    }


}
    void speedUp(int increment){
</pre>
    // method implementation
    }


=Comparison=
    void applyBrakes(int decrement){
From the above code samples, besides the syntax, we can see one major difference between Ruby mixins and Java interfaces:
    // method implementation
*a Ruby mixin adds behavior to the host class while a Java interface does not.
    }
In the Ruby sample the host class inherits from the ''Introspect'' module the '''behavior''' of the ''kind'' method while in Java the class that implements an interface must code the behavior of the inherited methods itself.


}</pre>


{| class="wikitable" style="margin: 1em auto 1em auto;"
=Comparing Ruby mixins to Java interfaces=
|+ Ruby mixins vs Java interfaces feature comparison
These two diagrams from [http://www.slideshare.net/mbowler/ruby-for-java-programmers Ruby For Java Programmers] illustrates how inheritance is done by Ruby mixins and Java interfaces.
! scope="col" | Features
{|
! scope="col" | Ruby Mixins
! scope="col" | Java Interfaces
|-
! scope="row" | Add functionality/behavior to a class
| Yes. When a Ruby module gets mixed in a Ruby class, the class receives the implementation (behavior) of the methods defined in the module. || No. A Java interface "can contain only constants, method signatures, and nested types. There are no method bodies. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces." (Java Interface)
|-
|-
! scope="row" | Favor composition over inheritance
!Ruby Mixins
| Yes. The class that includes a module establishes a "use-a" relationship with the module. This is composition. || No. The class that implements an interface establishes a "is-a" relationship with the interface. This is inheritance.
!Java Interfaces
|-
|-
! scope="row" | The code of the mixin/interface interacts with the code of the class that includes/implements it
|[[File:rubymixin.png|200px]]
| Yes. A mixed-in module can implement methods in terms of the host's class methods. See the Enumerable example.|| No. An interface provides a set of method signatures that the host class must implement. An interface provides no implementation of methods.
|[[File:javainheritance.png|300px]]
|}
|}


==     Multiple Inheritance Support==
Now let's look at some of the differences and similarities between Ruby mixins and Java interfaces.
===Multiple independent protocols===
==Implementation Inheritance==
===Mix and match===
In Ruby, a class that includes a module inherits the implementation of the methods defined in the module as well as the instance variables defined in the module.
Mixin can inherit behavior of modules while Interface only inherit method signature.
 
In Java, a class that implements an interface inherits the signatures of the methods defined in the interface but it must provide with the implementation of the methods itself.
 
In the Ruby sample the host class inherits from the ''Introspect'' module the implementation of the ''kind'' method and therefore it can call the method right away.
 
The ability to call the inherited methods right away is good for rapid prototyping, but in Ruby, one should be aware that the <tt>include</tt> “statement makes a reference to a module. If multiple classes include that module they’ll all point to the same thing. If you change the definition of a method within that module, even while your program is running, all classes that include the module will exhibit the new behavior.” (Thomas [3] page 79)
 
Bloch reminds us that this is one of the risks of ''implementation inheritance'': for its proper function, the host class may depend on the implementation of the included module. If the implementation of the included module changes the host class may brake. (Bloch [1] page 81)


===Submodularity===
Another risk associated to ''implementation inheritance'' in Ruby is that "mixed-in module's instance variables can clash with the ones of the host class or with the ones of other mixins."(Thomas [3] page 82)
===Separation of interface and implementation===
 
Java interface ensures the seperation of interface and implementation, while mixin can also simulate it, mixin needs to be handuled more cautiously to separate interface and implementation.
For example the following module adds the instance variable ''@observer_list''
 
<pre>
module Observable
  def observers
    @observer_list ||= []
  end
  def add_observer(obj)
    observer << obj
  end
  def notify_observers
    observers.each {|o| o.update}
  end
end
</pre>
but a class that includes the module could also use an instance variable named ''@observer_list''
<pre>
class TelescopeScheduler
  # other classes can register to get notifications when the schedule changes
  include Observable
  def initialize
    @observer_list = []  # people with telescope time
  end
  def add_viewer(viewer)
    @observer_list << viewer
  end
end
</pre>
If this happens, Thomas states that, at runtime, the TelescopeScheduler could malfunction in ways difficult to diagnose. (Thomas [3] page 82)
 
With Java interfaces this problem cannot happen because there's no implementation inheritance: Any field you declare in an interface is automatically public static and final, in other words a constant and not an instance variable that can be inherited.
 
==Separation of interface and implementation==
Java interfaces ensure the separation of interface and implementation by requiring the implementing classes to implement all the methods inherited from the interfaces.
Ruby does not enforce this separation in mixins.


Java interface can ensure the class implements from the interface provides its own method definitions, while Ruby mixin does not provide such reassurance.


For example we have a <tt>Shape</tt> interface, and a <tt>Circle</tt> class that implements <tt>Shape</tt>
For example we have a <tt>Shape</tt> interface, and a <tt>Circle</tt> class that implements <tt>Shape</tt>
Line 129: Line 162:
</pre>
</pre>


If Circle class does not provide a <tt>draw</tt> method, the class wil not compile.
If the Circle class does not provide a <tt>draw</tt> method, the class will not compile.


However, in case of Ruby, a class inherits all the behavior from a module, it does not require to overload the methods within the module.
However, in Ruby, an interface can be simulated but a class does not require to override the inherited methods.


<pre>
<pre>
Line 149: Line 182:
</pre>
</pre>


==     Inheritance Problem Handling==
==Method name collision handling==
===Name Collision===
Method names collisions in Java interfaces are eliminated at compile time.
"A mixed-in module's instance variables can clash with the ones of the host class or with the ones of other mixins."(Thomas 82)
There are programming practices to avoid this potential problem.
 
Name collision is handled more carefully with Interface. The method clashes are eliminated during compile time.


Because of the unbound polymorphism nature, the return type of Ruby method is determined at run time. This allows a class inherits from two modules that include same method call with different return types.
Because of the unbound polymorphism nature, the return type of Ruby method is determined at run time. This allows a class inherits from two modules that include same method call with different return types.


In Java, a class cannot inherits from two interfaces that include same method with different return type, due to the name conflict.  
In Java, a class cannot inherit from two interfaces that include same method with different return type, due to the name conflict.  
For example,
For example,
<pre>
<pre>
Line 209: Line 238:


In Ruby the latest method definition always overloads the previous one, therefore, the name collision needs to be handled more carefully.
In Ruby the latest method definition always overloads the previous one, therefore, the name collision needs to be handled more carefully.
To avoid name clashes at the origin each module could prefix the name of a method with the name of the module so that the two modules in the previous example could become
<pre>
module M1
    def M1method1
    "this is M1method1"
    end
end
module M2
    def M2method1
        "this is M2method1"
    end
end
class Myclass
include M1
include M2
end
puts Myclass.new.M1method1
puts Myclass.new.M2method1
=>this is M1method1
=>this is M2method1
</pre>
== Ruby mixins vs. Java interfaces feature comparison ==
Now lets look at some features Ruby mixin provides and compare it with Java interface.
{| class="wikitable" style="margin: 1em auto 1em auto;"
|-
! scope="col" | Features
! scope="col" | Ruby Mixins
! scope="col" | Java Interfaces
|-
! scope="row" | Add functionality/behavior to a class
| Yes. When a Ruby module gets mixed in a Ruby class, the class receives the implementation (behavior) of the methods defined in the module. || No. A Java interface "can contain only constants, method signatures, and nested types. There are no method bodies. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces." (Java Interface)
|-
! scope="row" | Favor composition over inheritance
| Yes. The class that includes a module establishes a "use-a" relationship with the module. This is composition. || No. The class that implements an interface establishes a "is-a" relationship with the interface. This is inheritance.
|-
! scope="row" | The code of the mixin/interface interacts with the code of the class that includes/implements it
| Yes. A mixed-in module can implement methods in terms of the host's class methods. See the Enumerable example.|| No. An interface provides a set of method signatures that the host class must implement. An interface provides no implementation of methods.
|}


= Examples=
= Examples=
We are going to compare mixin and interface implementions by looking at some code examples.  
We are going to compare mixin and interface implementations by looking at some code examples.  
== Comparable==
== Comparable==
<tt>Comparable</tt> provides a set of operations that can be used to compare two objects.
<tt>Comparable</tt> provides a set of operations that can be used to compare two objects.
Line 374: Line 449:


== Enumerable==
== Enumerable==
The <tt>Enumerable</tt> pattern is used to describe a set of fix contants.  
The <tt>Enumerable</tt> pattern is used to describe a set of fix constants.  
=== In Ruby===
=== In Ruby===
<tt>Enumerable</tt> is a standard mixin in Ruby that can be included in any class. A class wants to use <tt>Enumerable</tt> funcation needs to define <tt>each</tt> method.
<tt>Enumerable</tt> is a standard mixin in Ruby that can be included in any class. A class wants to use <tt>Enumerable</tt> functions need to define <tt>each</tt> method.


Consider a class takes a string and change the words to uppercase.  
Consider a class takes a string and change the words to uppercase.  
Line 464: Line 539:
Another approach is to implement the [http://en.wikipedia.org/wiki/Decorator_pattern Decorator] design pattern. In this case the new behavior is added not statically to classes at compile time but to specific objects/instances at run time.
Another approach is to implement the [http://en.wikipedia.org/wiki/Decorator_pattern Decorator] design pattern. In this case the new behavior is added not statically to classes at compile time but to specific objects/instances at run time.
=Conclusion=
=Conclusion=
In comparison with Java interface, Ruby mixin provides more flexibility and functionality. Ruby mixin can include behavior to a class. It makes mix and match of several classes easy. It also includes many standard mixins such as Singleton, Comparable, Enumerable and Datamapper, these standard modules make these design patterns easy to use and inherit functions by new objects. While Ruby mixin might seem more powerful than Java interface, Java interface still have its advantage over Ruby mixin in some cases. Java interface handles separation of interface and implementation better, it also handles name collision more strictly than Ruby mixin. Furthermore, when Ruby class includes a module, it gets a reference of the module, which increases coupling between the class and the included module. If the included module changes during runtime the class might result in some unexpected behavior.
=References=
=References=


[http://www.slideshare.net/mbowler/ruby-for-java-programmers Bowler]
1. Joshua Bloch, "Effective Java". Second Edition. May 2008, Prentice Hall.


Thomas Dave, "Programming Ruby 1.9" textbook
2. [http://www.slideshare.net/mbowler/ruby-for-java-programmers Ruby For Java Programmers] by Mike Bowler.


[http://download.oracle.com/javase/tutorial/java/IandI/createinterface.html Java Interface]
3. Dave Thomas, Chad Fowler, Andy Hunt, "Programming Ruby 1.9: The Pragmatic Programmers' Guide (Facets of Ruby Series)". Third Edition. April 2009, Pragmatic Bookshelf.
 
[http://martinfowler.com/eaaCatalog/dataMapper.html Data Mapper Design Pattern]
4. [http://download.oracle.com/javase/tutorial/java/IandI/createinterface.html Java Interface] From oracle.com, the Java Tutorials.
 
[http://datamapper.org/ Data Mapper in Ruby]
 
[http://code.google.com/p/mybatis/ Data Mapper in Java]
 
=draft material=
 
-- ''This is not the introduction yet. It's just an attempt to directly answer the questions from the teacher'' --
 
 
Functionality such as Comparable is done in Java with interfaces and in Ruby with mixins. 
 
Is there an advantage in using one or another?
 
''In Ruby, you only have to provide the logic for the <tt><==></tt> method and you'll get the <tt><, >, <=, >=, == , between</tt> methods for free. In Java, when you implement the <tt>Comparable</tt> interface you'll have to provide the logic for the <tt>></tt>, <tt><</tt> and <tt>==</tt> comparisons. You'll have to code the logic for <tt><=, >=, between</tt> yourself outside of the <tt>Comparable</tt> interface if you need those functions. In this case Ruby, out of the box, gives you more than Java.''
 
 
Consider other behaviors achieved with mixins in Ruby: Singleton, Enumerable, and DataMapper, for example.
 
Could you accomplish these with interfaces in Java?
 
''In Ruby, when a class includes the <tt>Singleton</tt> module it'll automatically becomes a singleton. In Java, you have to implement the <tt>Singleton</tt> design pattern in each class that you want to be a singleton. In this case Ruby allows you to write less code than Java.''
 
 
''Also in relation to the DataMapper design pattern, it seems more straightforward using the DataMapper Ruby gem then a Java library such as mybatis. ''
 
 
 
Does this mean that mixins are more powerful?
 
''Mixins are more powerful than interfaces because they add behavior to the mixee.''


5. [http://en.wikipedia.org/wiki/Mixin Mixin] From Wikipedia, the free encyclopedia.


6. [http://martinfowler.com/eaaCatalog/dataMapper.html Data Mapper Design Pattern] From Martin Fowler.


Or can interfaces achieve some purposes that mixins can't?
7. [http://datamapper.org/ Data Mapper in Ruby] From DataMapper, Ruby Object Relational Mapper.


''I see nothing that an interface can do while a mixin cannot. It's true that via an interface the existence of a method can be checked at compile time rather than at run time, but I'm not sure if this advantage can be attributed strictly to interfaces rather than to the Java language itself.''
8. [http://code.google.com/p/mybatis/ Data Mapper in Java] From mybatis - SQL mapping framwork for Java.


== Modules in Ruby==
9. [http://cglib.sourceforge.net/ cgilb] From Code Generation Library, [http://cglib.sourceforge.net sourceforge.net].
Modules in Ruby are a way to group together methods, classes and constants. They are similar to namespaces in languages such as C++. (From lecture 6 note)
== Mixin using Modules==
The most interesting use of modules is to define mixins. When you include a module within a class, all its functionality becomes available to the class. Not only can modules contain class methods; they can also contain instance methods. (From lecture 6 note)


=== Early/static binding (Java) ===
10. [http://code.google.com/p/javadude/wiki/AnnotationsMixinExample Java annotations processor] From AnnotationsMixinExample, JavaDude OpenSource Projects.
All method invocations must be defined at compile time. (Bowler)
=== Late/dynamic binding (Ruby) ===
The runtime does not check that a given method exists until an attempt to invoke it. (Bowler)
=== Multiple Inheritance ===
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.
(From Wikipedia, http://en.wikipedia.org/wiki/Multiple_inheritance)
=== Inheritance vs Composition ===
"Inheritance represents an incredibly tight coupling of two components. Change a parent class and you risk breaking the child class. But even worse, if code that uses objects of the child class relies on those objects also having methods defined in the parent, then all that code will brake too." (Thomas 84)


In Ruby, “the include statement makes a reference to a module. If multiple classes include that module they’ll all point to the same thing. If you change the definition of a method within that module, even while your program is running, all classes that include the module will exhibit the new behavior.” (Thomas 79)
11. [http://en.wikipedia.org/wiki/Decorator_pattern Decorator pattern] From Wikipedia, the free encyclopedia.

Latest revision as of 05:11, 30 September 2011

Ruby mixins versus Java interfaces

To inherit from multiple sources Ruby uses mixins while Java uses interfaces. This article explains both mechanisms, finds similarities and highlights differences between the two. Some code samples show the practical use of both mechanisms. The article also tries to remark situations where the use of one mechanism would be more appropriate than the other.

Ruby mixins

In Ruby a mixin happens when a module is included/mixed into a class or into another module.

A module is "a way of grouping together" different elements like class/instance methods, classes, instance variables and constants.(Thomas [3] page 76)

# module Introspect defines a method named 'kind'
module Introspect
  def kind
    puts "#{self.class.name}"
  end
end

A module cannot be instantiated but it can be included/mixed into another class

# The Animal and the Car classes include/mix in the module Introspect
class Animal
  include Introspect
end

class Car
  include Introspect
end

The class that includes a module inherits anything that the module defines.

d = Animal.new
c = Car.new

# the method 'kind' is inherited from the Introspect module
puts d.kind
puts c.kind

# outputs
Animal
Car

Notice that the code in the module has access to variables of the host class. In this sample the kind method defined in the Introspect module accesses the self variable of the host class (either Animal or Car).

Java interfaces

In its most common form, an interface is a group of related methods with empty bodies. A bicycle's behavior, if specified as an interface, might appear as follows:

interface Bicycle {

       void changeGear(int newValue);

       void speedUp(int increment);

       void applyBrakes(int decrement);
}

To implement this interface, the name of your class would change (to a particular brand of bicycle, for example, such as ACMEBicycle), and you'd use the implements keyword in the class declaration:

class ACMEBicycle implements Bicycle {

    void changeGear(int newValue){
    	// method implementation
    }

    void speedUp(int increment){
    	// method implementation
    }

    void applyBrakes(int decrement){
    	// method implementation
    }

}

Comparing Ruby mixins to Java interfaces

These two diagrams from Ruby For Java Programmers illustrates how inheritance is done by Ruby mixins and Java interfaces.

Ruby Mixins Java Interfaces

Now let's look at some of the differences and similarities between Ruby mixins and Java interfaces.

Implementation Inheritance

In Ruby, a class that includes a module inherits the implementation of the methods defined in the module as well as the instance variables defined in the module.

In Java, a class that implements an interface inherits the signatures of the methods defined in the interface but it must provide with the implementation of the methods itself.

In the Ruby sample the host class inherits from the Introspect module the implementation of the kind method and therefore it can call the method right away.

The ability to call the inherited methods right away is good for rapid prototyping, but in Ruby, one should be aware that the include “statement makes a reference to a module. If multiple classes include that module they’ll all point to the same thing. If you change the definition of a method within that module, even while your program is running, all classes that include the module will exhibit the new behavior.” (Thomas [3] page 79)

Bloch reminds us that this is one of the risks of implementation inheritance: for its proper function, the host class may depend on the implementation of the included module. If the implementation of the included module changes the host class may brake. (Bloch [1] page 81)

Another risk associated to implementation inheritance in Ruby is that "mixed-in module's instance variables can clash with the ones of the host class or with the ones of other mixins."(Thomas [3] page 82)

For example the following module adds the instance variable @observer_list

module Observable
  def observers
    @observer_list ||= []
  end
  def add_observer(obj)
    observer << obj
  end
  def notify_observers
    observers.each {|o| o.update}
  end
end

but a class that includes the module could also use an instance variable named @observer_list

class TelescopeScheduler
  # other classes can register to get notifications when the schedule changes
  include Observable
  def initialize
    @observer_list = []  # people with telescope time
  end
  def add_viewer(viewer)
    @observer_list << viewer
  end
end

If this happens, Thomas states that, at runtime, the TelescopeScheduler could malfunction in ways difficult to diagnose. (Thomas [3] page 82)

With Java interfaces this problem cannot happen because there's no implementation inheritance: Any field you declare in an interface is automatically public static and final, in other words a constant and not an instance variable that can be inherited.

Separation of interface and implementation

Java interfaces ensure the separation of interface and implementation by requiring the implementing classes to implement all the methods inherited from the interfaces. Ruby does not enforce this separation in mixins.


For example we have a Shape interface, and a Circle class that implements Shape

package interfaces;

public interface Shape {
	public void draw();
}

package classes;

import interfaces.Shape;

public class Circle implements Shape{
	public void draw()
	{
		System.out.println("This method draws a circle");
	}
}

If the Circle class does not provide a draw method, the class will not compile.

However, in Ruby, an interface can be simulated but a class does not require to override the inherited methods.

module Shape
	def draw
		raise NoMethodError, "draw method is not defined for Shape"
	end
end

class Circle
	include Shape
end

puts Circle.new.draw

=>shape.rb:3:in `draw': draw method is not defined for Shape (NoMethodError)

Method name collision handling

Method names collisions in Java interfaces are eliminated at compile time.

Because of the unbound polymorphism nature, the return type of Ruby method is determined at run time. This allows a class inherits from two modules that include same method call with different return types.

In Java, a class cannot inherit from two interfaces that include same method with different return type, due to the name conflict. For example,

public interface I1 {
	public void method1();
}
public interface I2 {
	public int method1();
}

package classes;
import interfaces.I1;
import interfaces.I2;

public class Mul_inherit implements I1, I2{
...
}

The Mul_inherit class will give error since there are no ways to satisfy both method1 signatures from I1 and I2.

But with Mixin this example is allowed since

    1. A method always returns a value (nil if nothing is defined).

    2. The type of return object is determined at runtime.

module M1
    def method1
	#this method returns nothing"
    end
end

module M2
    def method1
        "returns a string"
    end
end

class Myclass
include M1
include M2
end

puts Myclass.new.method1

=>returns a string

In Ruby the latest method definition always overloads the previous one, therefore, the name collision needs to be handled more carefully.

To avoid name clashes at the origin each module could prefix the name of a method with the name of the module so that the two modules in the previous example could become

module M1
    def M1method1
	    "this is M1method1"
    end
end

module M2
    def M2method1
        "this is M2method1"
    end
end

class Myclass
include M1
include M2
end

puts Myclass.new.M1method1
puts Myclass.new.M2method1

=>this is M1method1
=>this is M2method1

Ruby mixins vs. Java interfaces feature comparison

Now lets look at some features Ruby mixin provides and compare it with Java interface.

Features Ruby Mixins Java Interfaces
Add functionality/behavior to a class Yes. When a Ruby module gets mixed in a Ruby class, the class receives the implementation (behavior) of the methods defined in the module. No. A Java interface "can contain only constants, method signatures, and nested types. There are no method bodies. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces." (Java Interface)
Favor composition over inheritance Yes. The class that includes a module establishes a "use-a" relationship with the module. This is composition. No. The class that implements an interface establishes a "is-a" relationship with the interface. This is inheritance.
The code of the mixin/interface interacts with the code of the class that includes/implements it Yes. A mixed-in module can implement methods in terms of the host's class methods. See the Enumerable example. No. An interface provides a set of method signatures that the host class must implement. An interface provides no implementation of methods.

Examples

We are going to compare mixin and interface implementations by looking at some code examples.

Comparable

Comparable provides a set of operations that can be used to compare two objects.

In Ruby

If a Ruby class wants to use Comparable functions, it needs to define a method called <=> (sometimes called “rocket”). Ones the rocket function is defined, we get a lot of comparison functions for free, such as <, >, <=, >=, == and the method between.


Suppose we have a Rectangle class.

class Rectangle
    attr_reader :x,:y
    def initialize(x,y)
	@x,@y=x,y
    end
end

Now we want to compare the area of two rectangles. We can do so by include the Comparable mixin.

class Rectangle
include Comparable
    def area
	x*y
    end
    def <=>(other)
	self.area<=>other.area
    end
end

The <=> function uses Comparable mixin of Fixnum class to compare the area of two rectangles. We can call the Comparable methods on Rectangle objects.

r1 = Rectangle.new(3,4)
r2 = Rectangle.new(4,5)
puts r1.area
if r1 < r2
   puts "The area of Rectangle 1 is smaller than Rectangle 2"
else if r1 > r2
   puts "The area of Rectangle 1 is larger than Rectangle 2"
else
   puts "The area of Rectangle 1 equals to Rectangle 2"
 end
end


=>12
=>The area of Rectangle 1 is smaller than Rectangle 2

In Java

Java provides Comparable interface. A Java class implements Comparable interface need to define compareTo method.

For the same Rectangle class example, we need to define compareTo method, and define each of the <=> operators within the method.

public class Rectangle implements Comparable {

	private int x,y;
	
	public Rectangle(int width, int length)
	{
		x=width;
		y=length;
	}
	
	public int area()
	{
		return x*y;
	}
	public int compareTo(Object otherRectangle)
	{
		/*
		 * If passed object is of type other than Rectangle, throw ClassCastException
		 */
		if(!(otherRectangle instanceof Rectangle)){
			 throw new ClassCastException("Invalid object");
		}
		/*
		 * If left operand less than right operand return -1
		 * If left operand greater than right operand return 1
		 * If left operand equals to right operand return 0
		 */
		int otherArea=((Rectangle)otherRectangle).area();
		if (this.area() < otherArea)
			return -1;
		else if (this.area() > otherArea)
			return 1;
		else
			return 0;
	}
}

compareTo function is then used on Rectangle object when comparing two Rectangle objects.

public class CompareRectangle {
	public void main(String args[]){
		
		Rectangle r1=new Rectangle(3,4);		
		Rectangle r2=new Rectangle(4,5);

		if (r1.compareTo(r2) < 0)
			System.out.println("The area of Rectangle 1 is smaller than Rectangle 2");
		if (r1.compareTo(r2) > 0)
			System.out.println("The area of Rectangle 1 is larger than Rectangle 2");
		if (r1.compareTo(r2)==0)
			System.out.println("The area of Rectangle 1 equals to Rectangle 2");
			
	}
}

Singleton

The Singleton design pattern ensures that only one instance of a particular class may be created for the lifetime of a program.

In Ruby

The singleton library contains the Singleton module that if mixed into a class will make the class a singleton. The Singleton module makes the mixee new method private and replaces it with a method called instance that when called returns a singleton instance of the mixee.

You do not have to code the singleton functionality inside each class that needs to be a singleton.

require 'singleton'

class Klass
      include Singleton
end

a,b  = Klass.instance, Klass.instance
=> [#<Klass:0x007fa7a28798e8>, #<Klass:0x007fa7a28798e8>]

a == b
=> true

Klass.new
NoMethodError: private method `new' called for Klass:Class

In Java

Each class that needs to be a singleton must implement the singleton functionality itself such as in the following example.

public class Singleton  {
    private static final Singleton instance = new Singleton();
 
/**
Private constructor prevents instantiation from other classes
**/
    private Singleton() {
    }
 
    public static Singleton getInstance() {
        return instance;
    }
}

Enumerable

The Enumerable pattern is used to describe a set of fix constants.

In Ruby

Enumerable is a standard mixin in Ruby that can be included in any class. A class wants to use Enumerable functions need to define each method.

Consider a class takes a string and change the words to uppercase.

class WordToUpper
include Enumerable
    attr_reader :string
    def initialize(string)
	@string=string
    end
    def each
	@string.upcase.scan(/\w/) do |upper|
	  yield upper
        end
    end
    def to_s
        self.each{|a| puts a}
    end
end

Now that each method is defined we can use inject method from Enumerable mixin.

puts WordToUpper.new("Rudolph is a Ring Deer!").inject{|v,n| v+n}

=>RUDOLPHISARINGDEER

In Java

In Java there is no interface comparable to the Enumerable mixin in Ruby defined. Java can simulate the use of Enumerable by using Iterator class. However, it is not as convenient as have a Enumerable interface.

import java.util.*;

public class EnumerableExample {
	public static void main(String args[])
	{
	    //removal of items requires an explicit iterator :
	    Collection<String> words = new ArrayList<String>();
	    words.add("Rudolph");
	    words.add("is");
	    words.add("a");
	    words.add("red");
	    words.add("nose");
	    words.add("ring");
	    words.add("deer");
	    for(Iterator<String> iter = words.iterator(); iter.hasNext();){
	      if (iter.next().length() == 4){
	        iter.remove();
	      }
	    }
	}
}

In this example, we removed all strings with length of 4 in the Collection.

DataMapper

Martin Fowler describes the Data Mapper design pattern as "a layer of software that separates the in-memory objects from the database. Its responsibility is to transfer data between the two and also to isolate them from each other. With Data Mapper the in-memory objects needn't know even that there's a database present; they need no SQL interface code, and certainly no knowledge of the database schema. (The database schema is always ignorant of the objects that use it.)"(Data Mapper)

In Ruby

The DataMapper Ruby library was originally developed to address perceived shortcomings in Ruby on Rails' ActiveRecord library. For example DataMapper lets you avoid writing raw query fragments yourself. It allows you to write

Zoo.all(:name => 'Dallas')

instead of

Zoo.find(:all, :conditions => [ 'name = ?', 'Dallas' ])

In Java

The mybatis SQL Mapping Framework implements the Data Mapper design pattern. Its setup and use though seem more complicated than the DataMapper Ruby library.

Mixins in Java

Java does not support mixins natively.

Different approaches try to reproduce the mixin feature in Java.

One example is the cgilb Java library. It provides the Mixin class that allows multiple objects to be combined into a single larger object at run time. The methods in the generated object simply call the original methods in the underlying "delegate" objects.

A similar result is achieved at compile time by this Java annotations processor. Let's say for example that you want to combine/mix the functionality of three classes into one class. You can write a Java annotation that declares which classes you want to mix, then you pass this annotation to the annotation processor and you get the source code of a class that combines all the three behaviors.

Another approach is to implement the Decorator design pattern. In this case the new behavior is added not statically to classes at compile time but to specific objects/instances at run time.

Conclusion

In comparison with Java interface, Ruby mixin provides more flexibility and functionality. Ruby mixin can include behavior to a class. It makes mix and match of several classes easy. It also includes many standard mixins such as Singleton, Comparable, Enumerable and Datamapper, these standard modules make these design patterns easy to use and inherit functions by new objects. While Ruby mixin might seem more powerful than Java interface, Java interface still have its advantage over Ruby mixin in some cases. Java interface handles separation of interface and implementation better, it also handles name collision more strictly than Ruby mixin. Furthermore, when Ruby class includes a module, it gets a reference of the module, which increases coupling between the class and the included module. If the included module changes during runtime the class might result in some unexpected behavior.

References

1. Joshua Bloch, "Effective Java". Second Edition. May 2008, Prentice Hall.

2. Ruby For Java Programmers by Mike Bowler.

3. Dave Thomas, Chad Fowler, Andy Hunt, "Programming Ruby 1.9: The Pragmatic Programmers' Guide (Facets of Ruby Series)". Third Edition. April 2009, Pragmatic Bookshelf.

4. Java Interface From oracle.com, the Java Tutorials.

5. Mixin From Wikipedia, the free encyclopedia.

6. Data Mapper Design Pattern From Martin Fowler.

7. Data Mapper in Ruby From DataMapper, Ruby Object Relational Mapper.

8. Data Mapper in Java From mybatis - SQL mapping framwork for Java.

9. cgilb From Code Generation Library, sourceforge.net.

10. Java annotations processor From AnnotationsMixinExample, JavaDude OpenSource Projects.

11. Decorator pattern From Wikipedia, the free encyclopedia.