CSC/ECE 517 Summer 2008/wiki1 3 jb: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 92: Line 92:
*Java code is more difficult to read and write due to required exception handling
*Java code is more difficult to read and write due to required exception handling
*method method in Ruby doesn't allow full signature matching since both return values and parameters aren't included.
*method method in Ruby doesn't allow full signature matching since both return values and parameters aren't included.
*Java requires an extra step in querying for a method, by requiring that you retrieve the an instance of a Class object first. In Ruby, you can query the object directly for a method.


==Conclusions==
==Conclusions==

Revision as of 01:44, 4 June 2008

This wiki will explore how reflection is implemented with both Java and Ruby, with the goal of showing which language's implementation makes it easier to write, easier to understand, and more efficient. Reflection refers to the ability of a program to peer inside itself and observe the components that it is comprised of. Reflection, as supported in Object Oriented languages such Java and Ruby, provides facilities to query about the methods and attributes of a specified class, and to execute methods that are discovered at runtime. These two features of reflection in Java and Ruby will explored in detail below.

To illustrate the concept of reflection, a simple example will be implemented in both Java and Ruby. The data model in the example will consist of a mountain bike class and disc brake class. A mountain bike in this example is composed of disc brakes. The mountain bike class will expose a public setter method method to set the disc brakes object. This setter method will be queried for by name at runtime, and executed.


Reflection in Java

The following is an implementation of the example in Java. A detailed description of the code follows.


  import java.lang.reflect.*;
  
  class DiscBrakes { }
  
  class MountainBike
  {
  	private DiscBrakes m_discBrakes = null;
  
  	public boolean hasDiscBrakes() { return m_discBrakes != null; }
  	public void setDiscBrakes(DiscBrakes discBrakes) { m_discBrakes = discBrakes; }
  
  	public static void main (String argv[])
  	{
  		Class c = MountainBike.class;
  
  		MountainBike mb = new MountainBike();
  		DiscBrakes db = new DiscBrakes();
  		Method meth = null;
  
  //		Class c = mb.getClass();
  
  		System.out.println(mb.hasDiscBrakes());
  
  		try 
  		{
  			meth = c.getMethod("setDiscBrakes", DiscBrakes.class);
  		}
  		catch (NoSuchMethodException e) { }
  
  		try
  		{
  			meth.invoke(mb, db);
  		}
  		catch (IllegalAccessException e) { }
  		catch (InvocationTargetException e) { }
  			
  		System.out.println(mb.hasDiscBrakes());
  	}
  }
  • The first thing to note in the Java implementation is the import of the java.lang.reflect package.
  • The next thing to note is the first statement within the main method. An instance of the Class class is retrieved from the MountainBike class' static variable. The Java Object class, the base class of all objects, provides the Class member variable to expose reflection capabilities. Notice also that an instance of a Class can also be obtained from an instance of an object by calling the getClass method.
  • Next, a Method object is retrieved from the Class object, via the getMethod method. The getMethod method takes a method name as a String, and a variable length list of Class objects for arguments. In this case, the setDiscBrakes method takes an instance of the DiscBrakes class as a parameter.
  • Finally, the Method object's invoke method is used to call the setDiscBrakes method on an instance of the MountainBike class. The invoke method takes as its first parameter, the object on which to invoke the method, and then a variable length list of Objects for arguments.

Reflection in Ruby

The following is an implementation of the example in Ruby. A detailed description of the code follows.

class DiscBrakes
end

class MountainBike
  @m_discBrakes = nil
  def hasDiscBrakes 
      return @m_discBrakes != nil
  end
  def setDiscBrakes(discBrakes)
    @m_discBrakes = discBrakes
  end
end

mb =  MountainBike.new

puts mb.hasDiscBrakes

db = DiscBrakes.new
setter = mb.method("setDiscBrakes")
setter.call(db)

puts mb.hasDiscBrakes
  • The first thing to note in the Ruby implementation is the retrieval of the setter method directly from the instance of the MountainBike object. This happens towards the bottom of the example code.
  • Next, and finally, the call method is invoked on the method object. An instance of the DiscBrakes is passed off as a parameter.

Comparison

  • getMethod method in Java doesn't allow full signature matching since return values aren't included.
  • Java code is more difficult to read and write due to required exception handling
  • method method in Ruby doesn't allow full signature matching since both return values and parameters aren't included.
  • Java requires an extra step in querying for a method, by requiring that you retrieve the an instance of a Class object first. In Ruby, you can query the object directly for a method.

Conclusions

Java Reflection Links

Pros and cons of reflection, written for Java but pretty generic
Using Java reflection
Javadoc for the java.lang.Class class
Javadoc for the java.lang.reflect package


Ruby Reflection Links

Good overview of reflection in Ruby
Rubydoc for the method method of class Object
Rubydoc for the Method class