CSC/ECE 517 Fall 2011/ch1 2c rs
Here we discuss about interfaces in Java, mixins in Ruby and compare some of the functionalities offered by mixins and the corresponding behaviors if exhibited by the interfaces.
Interfaces in Java
An interface in java is a collection of related methods with empty bodies, constant declarations ,nested types. It is declared using a key word ‘interface’. Constants are implicitly static and final. The methods are implicitly public, an interface cannot be instantiated as it is incomplete i.e, the methods are only declared but not defined. It can only be extended by other interfaces or implemented by classes. An interface can extend any number of interfaces.
An interface can be defined in the following manner.
interface <interface name> { <constants> <method declarations> }
A variable whose declared type is an interface type can hold a reference to an object of a class (or its subclass) that has implemented this interface.
Contractual Obligation:
A class that implements an interface has to provide a definition for each method of the inferface or has to be declared as an abstract class if it fails to implement even one method specified in the interface. An error message is issued by the compiler if the class does not define all the methods of an interface it has agreed to define. Even unrelated classes can implement an interface.
Example of an Interface:
In the following example, we create an interface called 'Shape' with the methods 'draw' and 'displayArea'. A class 'Square' implements the interface 'Shape' by provided definitions for the methods 'draw' and 'displayArea'. In the main method we create an object of Square and call the methods. Note that a 'Shape' variable can be used to hold the reference to the object of 'Square'
interface Shape { void draw(); void displayArea(float a,float b); } class Square implements Shape { public void draw() { System.out.println("Drawing Square"); } public void displayArea(float a,float b) { System.out.println("Area is "+a*b); } } public class InfDemo { public static void main(String args[]) { Square s=new Square(); s.draw(); s.displayArea(5,5); } }
Output:
Drawing Square Area is 25.0
Some benefits of Interfaces in Java
- Interfaces allow an object to play several roles.ie They can be used to simulate multiple inheritance.
- They help the developer to design the skeleton behavior for classes.
- An interface can also be used for creating a class that can store application level constants.
- Interfaces are very useful when publishing APIs
Modules in Ruby
A Module in ruby is a way of grouping together methods,variables and classes. It is similar to the idea of namespace. A module has the same implementation and is similar to a ruby class except for a few significant differences:
- Instance of a module cannot be created.
- It cannot be inherited by other classes but can be 'included'. (including a module in a class definition can roughly mean that the methods are appended to the class).
- The syntax for defining a module is different.
A module can be defined as follows :
module <Module Name> #define methods #define classes #define constants end
Example: Consider a requirement where a person must bow to a good guy and hit the bad guy with a bow.
The module 'GoodGuy' implements a method 'bow' and tells the caller to bow to the guy because he is a good guy.
module GoodGuy def GoodGuy.bow puts "I bow to you. you are a good guy" end end
There is another module 'BadGuy' which implements the same method bow but tells the caller to hit the guy with a bow because he is a bad guy.
module BadGuy def BadGuy.bow puts "I will hit you with a bow.you are a bad guy" end end
A third program which wants to use these modules can load the files using 'require' keyword and can refer to the methods using the qualified names. Note: A module's method can be called by <Module name>.<method name> and module constants are referred as <Module_name>::<method name>
require 'GoodGuy' #require is used to load and execute the code once. require 'BadGuy' GoodGuy.bow BadGuy.bow
Mixins in Ruby
History of Mixins
Mixins are not something new. Smalltalk supported them way back in 1971.According to wikipedia, Mixins first appeared in the Symbolics' object-oriented Flavors system (developed by Howard Cannon), which was an approach to object-orientation used in Lisp Machine Lisp. The name was inspired by Steve's Ice Cream Parlor in Somerville, Massachusetts The ice cream shop owner offered a basic flavor of ice cream and blended in a combination of extra items and called the item a "Mix-in", his own trademarked term at the time .
Mixins
Mixins are used to make certain behavior(s) available to a class.
Lets assume that the two modules(module 'GoodGuy'and 'BadGuy') in the above example were classes. Ruby is single-inherited, so the same functionality (ie a person must bow to a good guy and hit the bad guy with a bow). as above cannot be implemented through a class as we need to extend both the GoodGuy class and the BadGuy class which is not possible. Through modules, Ruby provides simulation of excellent feature of multiple inheritance. Any functionality of any module can be imported into our class. Thus, the features of the module gets “mixed-in” with our class.
Example of Mixins:Here we define a class to extend both the modules and call the same 'bow' method of the two modules from the object of our class.
require 'GoodGuy' require 'BadGuy' class Actnow include 'GoodGuy' include 'BadGuy' def Act(kind) if(kind=='good') GoodGuy.bow end if (kind =='bad') BadGuy.bow end end end myobj=Actnow.new myobj.Act('good') myobj.Act('bad')
Note: The methods of the module do not belong to the class 'requiring' it. To make a module's method the instance methods of our class, we have to use include instead of require. However, to include a module which is in a separate file, we have to use both the keywords 'require' and 'include'. This does not mean that these methods are copied into the class definition. Using 'includes <module name>' just references the module’s method from our class. Thus, any modifications made to the method definition in the module even at run time are reflected in the class.
Some Pre-defined mixin modules
Ruby has the following built into modules: Comparable, Enumerable,FileTest, GC, Kernel,Math, ObjectSpace,Precision , Process, Signal.
Comparable is a mixin module which permits the including class to implement comparison operators. The including 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?.
Enumerable is a mix-in module for enumeration. The including class must provide the method each.
FileTest is a module containing file test functions; its methods can also be accessed from the File class. The GC module provides an interface to Ruby’s mark and sweep garbage collection mechanism. Some of the underlying methods are also available via the ObjectSpace module. Kernel is a module included by the Object class; it defines Ruby’s ‘built-in’ methods.
Math is a module containing module functions for basic trigonometric and transcendental functions.
ObjectSpace is a module which contains routines that interact with the garbage collection facility and allows traversing all living objects with an iterator.
Precision is a mixin for concrete numeric classes with precision
Comparable Behavior
The comparable functionality is useful when there is a requirement to compare few objects and maybe even sort them.
In Ruby the comparable behavior is achieved by simply defining the <=>operator(which returns -1,0,1 depending on whether the argument object is greater than, equal to or less-than the calling object) and including the Comparable mixin. Consider a situation where we have a class Organization and this Organization stores the information about several Organizations. Suppose we have to sort different organizations in ascending order as to which is greater by comparing only total revenue of each. The implementation in Ruby is as follows.
Example of Comparable in Ruby:
class Org include Comparable attr :name attr :revenue attr :emplCount def initialize(name,revenue,emplCount) @name = name @revenue=revenue @emplCount=emplCount end def <=>(second) self.revenue <=> second.revenue end def to_s "#{name}" end end org1=Org.new('org1',100000,5000); org2=Org.new('org2',100001,4000); org3=Org.new('org3',100002,4000); org4=Org.new('org4',100003,4000); org5=Org.new('org5',100004,4000); a=[org1,org2,org3,org4,org5]; puts a.sort
output:
org1 org2 org3 org4 org5
In Java, there is an interface called Comparable which declares an abstract method called CompareTo. Several pre-defined classes such as Float,Double,Integer,Long implement this interface and provide a definition for the CompareTo method. If we have to compare two objects of our class by comparing a specific attribute of the objects, we need to implement the interface in our class and provide the implementation of the CompareTo method by writing our code in there to compare the two objects of that class. Consider the same example as above and the implementation for java is provided below.
Example of Comparable in Java:
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; //import java.util.*; public class Org implements Comparable { String name; Integer revenue; int emplCount; public Org(String name,Integer revenue, int emplCount) { this.name=name; this.revenue=revenue; this.emplCount=emplCount; } public int compareTo(Object obj1) { if (this.revenue == ((Org) obj1).revenue) return 0; else if ((this.revenue) > ((Org) obj1).revenue) return 1; else return -1; } public String toString() { return "Org " + name + "\n" ; } public static void main(String[] args) { List list1 = new ArrayList(); Org org1=new Org("org1",1000000,5000); Org org2=new Org("org2",1000001,4000); Org org3=new Org("org3",1000002,4000); Org org4=new Org("org4",1000003,4000); Org org5=new Org("org5",1000004,4000); Org org6=new Org("org6",1000005,4000); list1.add(org1); list1.add(org2); list1.add(org3); list1.add(org4); list1.add(org5); list1.add(org6); Collections.sort(list1); Iterator itr = list1.iterator(); System.out.println("The list of organizations in the ascending order of revenue are"); while(itr.hasNext()){ Object element = itr.next(); System.out.println(element + "\n"); } } }
Output:
The list of organizations in the ascending order of revenue are Org org1 Org org2 Org org3 Org org4 Org org5 Org org6
Enumerable Behavior
Enumerable module
Various operations are supported by the Ruby Collection classes .Some of such operations are traversing the collection, sorting the collection. We can define classes that can support these features on collections by including the enumerable module and defining an iterator ‘each’. This iterator has to return the elements of the collection in turn.
If the classes which have included the Enumerable module can implement the rocket method <=>, we can also use other methods like min, max ,sort on the collections.
Enumerable is a standard mixin implementing operators in terms of the ‘each’ method defined the host class. The host class is that class which includes the enumerable.
Usage of Enumerable
Ruby’s enumerable module has methods for all kinds of operations that can be performed on a collection. Collection objects which can be instances of Array,Hash etc. “mixin” the enumerable module.It gives objects of collections additional collection specific behaviors. These behaviors are given by the each method.
To Mix in Enumerable in a class,
Class MyCollection include Enumerable #other code def each #definiton end #othercode end
Some of the built in classes which mixin Enumerable are : String, Hash ,Array ,Range ,Struct. Each class that includes ‘Enumerable’ must define the ‘each’ method as per its own requirement.
eg: the Array class ‘s each method yields each element.The Hash class‘s each yields each key-value pair as a two element array.
Some Useful Methods offered by Enumerable:
- map: modifies each member according to the instructions in a block and returns the modified collection of members.
- collect: similar to map.
- grep: The grep method ‘searches’ for members using a regular expression
eg:
(1..10).grep (5..7) #=>[5,6,7]
- all? : It returns true if all elements of a collection satisfy the condition in the block ie the block never returns false or nil. If no block is specified it returns true if none of the collection members are false or nil.
eg:
%w{ant bear cat}.all? {|word| word.length >= 3} #=> true %w{ant bear cat}.all? {|word| word.length >= 4} #=> false
- any?
Passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil.
eg:
%w{ant bear cat}.any? {|word| word.length >= 3} #=> true %w{ant bear cat}.any? {|word| word.length >= 4} #=> true
One of the common and useful methods of enumerable is ‘inject’. We can use it in any class that includes enumerable and provides the implemation for ‘each’ method. This method applies a function or operation to the first two elements in the
collection and then applies the operation to the result of this computation and to the third
element, and so on, until all elements in the collection have been used.
Example of using Enumerable Mixin: In the below example, the class 'EnumerableDemo' includes the Enumerable mixin and provides the definition for 'each' which yields the digits present in a string. When inject method with the argument +,is called on the object of the class it returns a string of digits.
class EnumerableDemo include Enumerable def initialize(string) @string=string end def each @string.scan(/\d/) do |num| yield num end end ed=EnumerableDemo.new("123Bond007") puts ed.inject(:+)
output:
123007 #The numbers in a string are concatinated and returned.
In Java, the Collection interface specifies some methods similar to the methods of Enumerable module. For example contains can be mapped to find,to_array can be mapped to collect. etc. But the methods are also not as powerful as those of the Enumerable module methods. Also the implementation of these methods is not available unless we inherit from a class which implements this interface. This is unlike mixins in ruby where implementation of ‘each’ method provides us several useful collection methods for free.
Enumerable Interface in Java.
Java provides the Enumeration Interface. But its functionality is different from the Enumerable module of ruby.In Java, the Enumeration interface defines the methods by which you can enumerate (obtain one at a time) the elements in a collection of objects.
Successive calls to the nextElement method return successive elements of the series.
For example, to print all elements of a vector v:
for (Enumeration e = v.elements() ; e.hasMoreElements() ;) { System.out.println(e.nextElement()); }
hasMoreElements: Tests if this enumeration contains more elements.
nextElement: the next element of this enumeration.
Data Mapper
In any software development, we often face situations where our code has to interact with a database. In such situations, we have to have knowledge of a query language like SQL to insert into, delete from or modify a database. In modern programming languages, a feature called Object Relational Mapping is provided. This features allow the user to access the database tuples as if they were objects. All the database operations such as insert, delete,update,etc. are implemented in the language using objects. The programmer need not have a firsthand knowledge of a query language to perform these operations.
In Ruby, Object Relational Mapping is implemented using DataMapper. The DataMapper provides wide variety of features and is thread-safe(multiple threads can call it without interfering with each other.
Following are the steps involved in using the DataMapper<ref>http://ruby.about.com/od/sinatra/a/datamapper.htm</ref>.
Step 1: Install the dm-core ruby gem – the core of the DataMapper library. This gem has no external dependencies and so, we can install it in the same way we install other gems in ruby.
$sudo gem install dm-core
Step 2: We now need to install an adapter which allows the DataMapper to talk to the database. This is specific to each database provider. '
Eg: For SQLite 3
$ sudo apt-get install libsqlite3-dev $ sudo gem install dm-sqlite-adapter
Step 3: We then need to require the dm-core gem in our application.
Require ‘rubygems’ Require’data_mapper’ Require ‘dm-core’
Now, we have to specify the database connection to which our DataMapper must talk to. This is done using datamapper.setup
DataMapper.setup(:default, “[dataobject]://[relative-path]”) For SQLite, this would be something like this. DataMapper.setup( :default, "sqlite3://#databases/myown.db" )
Step-4 – Define models in a class using DataMapper:
The models can be created as below
# Create and define a class Recipee class Recipee include DataMapper::Resource property :Name, String: key => true property :type, String property :Description, text end
This model can be called using the DataMapper.auto_migrate command. This creates the table if it does not already exist. If the table already exists, it modifies the columns in this table. We can specify primary key by using the key=> true. The serial type is an auto increment integer key. We can create a column ID and define its type as serial to make it a key automatically. Now, we can access these as if they were objects without having knowledge about any query language to insert and update a table. the code
# Create a new record myrecipee = Recipee.new myrecipee.attributes = { :name => 'OrangeJuice', :type => 'beverage', :Description => 'Tasty!' } Insert: myrecipee.save to save Modify: myrecipee.Description=’Tasty and Delicious!’ Delete: Myrecipee.destroy to deletethe tuple in the database Select: puts myrecipee.inspect
DataMapper in Java
In java, Hibernate, iBatis are modern approaches that provide the ORM functionality. Traditionally, JDBC had to be used to access the databases.The functionalities provided by Hibernate are similar to that of DataMapper in ruby- it can access the database as objects.
Hibernate defines a language called HQL(Hybernate Query Language). HQL can be said to be the object oriented version of SQL. Java was created in 1995, but hibernate did not come into existence until 2001. Hibernate was developed by Redhat in Java to introduce ORM in Java.
Singleton Behavior
According to Wikipedia ,” In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. (This concept is also sometimes generalized to restrict the instance to a specific number of objects . This is useful when exactly one object is needed to coordinate actions across the system.”
The singleton design pattern is used when we desire only one instance of some class, such as one database connection, one logger instance or even one configuration object for an application.
In Ruby, the singleton behavior can be achieved by simply including the ‘Singleton’ Module.
To use ruby singleton module,
- ’require’ the ‘Singleton’ and then include it in desired class.
- Use the instance method to get the instance you need.
Ruby does the following when a singleton module is included in a class.
- New method is made private so that it can’t be used for instantiation.
- A class method called ‘instance’ is added that instantiates only one instance of the class.
Eg
class A include Singleton # ... end
this ensures that only one instance of A be created.
a,b = A.instance, A.instance a == b # => true A.new # NoMethodError - new is private ...
An instance is created at the first call of A.instance(), thus this behavior is preserved under inheritance and cloning.This is achieved by marking A.new as private nd providing (or modifying) the class methods A.inherited() and A.clone() - to ensure that the Singletonpattern is properly inherited and cloned.
In java, the singleton design pattern proposes that at any time there can be a single instance of an object created by JVM. To implement this behavior, the class’s default constructor is made private. This prevents the direct instantiation of the object. A static modifier is applied to the instance method that returns the object as it then makes this method a class level method that can be accessed without creating an object.
For implementing a singleton pattern, consider the following steps:
Step -1: Provide a default private constructor.
Step-2: Define a method to obtain the reference to the singleton Object.
Step 3: The Access method has to be made synchronized to prevent Thread Problems.
Step 4: The Object clone method has to be overridden to prevent cloning.
Example of Singleton:
class SingletonClass { private static SingletonClass singletonObject; /** A private Constructor prevents any other class from instantiating. */ private SingletonClass() { // Optional Code } public static synchronized SingletonClass getSingletonObject() { if (singletonObject == null) { singletonObject = new SingletonClass(); } return singletonObject; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } } public class SingletonObjectDemo { public static void main(String args[]) { // SingletonClass obj = new SingletonClass(); //Compilation error not allowed SingletonClass obj = SingletonClass.getSingletonObject(); // Your Business Logic System.out.println("Singleton object obtained"); } }
Mixin vs Interfaces
- What makes mixins so powerful is that the methods of the host class(the class that includes the module) can be accessed in the module even before we define the host class.
Example: In the following example,we define a module 'Wisher' which defines a method 'wish' that uses a method 'name' of the host class . Next we define the host class (Person) that includes 'Wisher' and hence obtains the 'wish' method of the module.The 'Person' class contains an attribute reader method 'name' and an initialize method. We then create an object 'p' of class 'Person' and call the method 'wish' on it.The 'wish' method uses method 'name' of Person to return a string as the output.
module Wisher def wish puts "Good Day "+self.name #name ie attr_reader method of the host class is used even before the class is define. end end class Person include Wisher def initialize(name,age) @name=name @age=age end attr_reader :name end p=Person.new (“James”,4) p.wish #returns Good Day James.
Such a feature is not supported by interfaces in java.
- Rewriting : When an interface is rewritten, all classes that implemented the older version are now broken because they no longer implement the interface. Hence the programmer has to try to anticipate all uses for the interface he/she is defining and specify it completely from the beginning. Such a problem is not caused in Ruby. Even if the module definition is changed at run-time, the classes that include the module use the modified version of the module.
- Both Java and Ruby support single inheritance.i.e, A class can inherit features from a single class. Multiple inheritance is achieved in Java through interfaces and in Ruby through Mixins. ie A java class can extend only one class but can implement several interfaces. Hence objects can have multiple types ie the type of their own class and the type of the interfaces that their class implements. Similarly a Ruby class can be subclassed from a single class but can include many modules.(mixins). In Ruby, inheritance and mixins allow us to write code at one place and reuse it in other classes. Inheritance is used when there is an “is-a” relationship. Mixins are used when there is a “uses a” or “has a” relationship. However there is no such advantage with interfaces in java . Hence there can be misuse of inheritance as even unrelated classes can implement an interface.
- One analogy that can be used to compare interfaces in java and mixins in ruby is that interface is like a legal contract while mixin is like a promise. ie a java interface is all about meeting the rules of the extra methods that must be provided where as in ruby there are no such rules to be enforced. Consider the comparable behavior for example. Both mixins and interfaces provide similar behavior. But if a class extends' Comparable' interface and fails to implement the 'compareTo' method a compile time error occurs even if the object of the class does not attempt to use the comparable behavior. But in cases of mixins, if a class includes ‘Comparable’ mixin and does not implement the <=> method there are no errors if the object of the class does not attempt to use the comparable behavior. Hence we can think of it as a promise. If the object uses the comparable behavior ie calls methods like >,<,between? etc only then a runtime error occurs.
eg: Consider the class 'A' which includes the 'Comparable' mixin.It defines a method 'hi'. It does not implement the <=> method. When an object 'a' of class 'A' is created and method 'hi' is invoked on it, there is no exception. But there will be a exception when the methods like <,>etc are used because the <=> method has not been implemented.
class A include Comparable def hi puts "hi" end end a=A.new a.hi #returns “hi”. In java,there would be a compilation error in such a scenario since the methods of the Interface are not implemented.
- Also classes implementing interfaces do not inherit code. ie there is no code reusability.An interface is purely something to help programs type-check in a statically typed language whereas mixins provide actual code to classes that include them. Hence mixins allow code reusability.
Conclusion
We have seen that some of the functionality of mixins is provided by interfaces in Java like the Comparable functionality for instance. However,we know that an interface only specifies what the class must support and cannot provide an implementation unlike a module which can be mixed into any number of classes. For refactoring common behavior into a single place in java (to achieve the power of mixins),we need another class which provides an implementation and is dependent on the interface.It has been observed that Interfaces when combined with aspect-oriented programming can produce full fledged mixins in Java.
References:
<references/>
http://solitude.vkps.co.uk/Archives/2009/01/13/data-mappers/
http://javatemple.blogspot.com/2008/11/features-of-hibernate-in-nutshell.html
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Comparable.html
http://www.tutorialspoint.com/ruby/ruby_modules.htm
http://www.javabeginner.com/learn-java/java-singleton-design-pattern
http://www.brainbell.com/tutorials/java/Applying_Some_Structure.htm
http://ruby-doc.org/
http://download.oracle.com/javase/tutorial
http://en.wikipedia.org/wiki/Mixin
http://en.wikipedia.org/wiki/Singleton_pattern