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

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(79 intermediate revisions by the same user not shown)
Line 1: Line 1:
This wiki will explore how <b>reflection</b> 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.
This wiki will explore how [http://en.wikipedia.org/wiki/Reflection_(computer_science) 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 is 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.  


==Basics==
To illustrate the concept of reflection, a simple example was implemented in both Java and Ruby. The data model in the example consists of a mountain bike class and disc brake class. A mountain bike in this example is composed of disc brakes. The mountain bike class exposes a public setter method to set the disc brakes object. This setter method will be queried for by name at runtime, and executed.
[http://en.wikipedia.org/wiki/Reflection_(computer_science) 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.


==Reflection in Java==
==Reflection in Java==


The following is an implementation of the example in Java. A detailed description of the code follows.
<pre>
<pre>
import java.lang.reflect.*;


class MountainBike
  import java.lang.reflect.*;
{
 
boolean diskBrakes() { return true; }
  class DiscBrakes { }
boolean knobbyTires() { return true; }
 
  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());
  }
  }
</pre>
 
*The first thing to note in the Java implementation is the import of the [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/package-summary.html java.lang.reflect] package. 
 
*The next thing to note is the first statement within the main method. An instance of the [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html Class] class is retrieved from the MountainBike class' static variable. The [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html 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 [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html Method] object is retrieved from the [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html 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.


public static void main (String argv[])
*Finally, the [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html Method] object's [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...) invoke] method is used to call the setDiscBrakes method on an instance of the MountainBike class. The [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...) 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.
{
Class c = MountainBike.class;
Method methods[] = c.getDeclaredMethods();
for (int i=0; i<methods.length; i++)
{
System.out.println(methods[i].getName());
}
}
}
</pre>


==Reflection in Ruby==
==Reflection in Ruby==
The following is an implementation of the example in Ruby. A detailed description of the code follows.
<pre>
<pre>
class DiscBrakes
end
class MountainBike
class MountainBike
   def diskBrakes
  @m_discBrakes = nil
       return true
   def hasDiscBrakes
       return @m_discBrakes != nil
  end
  def setDiscBrakes(discBrakes)
    @m_discBrakes = discBrakes
   end
   end
  def knobbyTires
      return true
    end
end
end


mb =  MountainBike.new
mb =  MountainBike.new
puts MountainBike.public_instance_methods(false)
 
puts mb.hasDiscBrakes
 
db = DiscBrakes.new
setter = mb.method("setDiscBrakes")
setter.call(db)
 
puts mb.hasDiscBrakes
</pre>
</pre>


==Conclusions==
* The first thing to note in the Ruby implementation is the retrieval of a [http://www.ruby-doc.org/core/classes/Method.html method] object for the setter, directly from the instance of the MountainBike object. This happens towards the bottom of the example code.
* Next, and finally, the [http://www.ruby-doc.org/core/classes/Method.html#M000444 call] method is invoked on the [http://www.ruby-doc.org/core/classes/Method.html method] object. An instance of the DiscBrakes class is passed off as a parameter.
<i>
Note, the [http://www.ruby-doc.org/docs/UsersGuide/rg/accessors.html attr_writer] feature of Ruby was intentionally not used for the sake of simplicity in keeping the two implementations as close as possible. In a Ruby only implementation, manual coding of the setter would not have been needed.
</i>
 
==Comparison==
We will now compare the sample implementations to determine which language makes it easier to program reflection, makes it easier to understand code that uses reflection, which is more efficient with regards to reflection.
 
===Which language makes it easier to program reflection?===
Reflection in Java is more difficult to write...
*due to required [http://en.wikipedia.org/wiki/Exception_handling exception handling]. The programmer is forced to deal with the fact that the api's in Java throw exceptions. This is an issue between the two languages that affects more than just Reflection, but it still has a definite impact on how reflection is coded up.
*since the reflection api is not built into every [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html Object]. Java requires an extra step when querying for a method, by requiring that you retrieve the an instance of a [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html Class] object first. In Ruby, you can query an object directly for a method.
*since you have to first include the [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/package-summary.html java.lang.Reflect] package. This is closely related to the previous point, in that the reason that the package needs to be included is that the capability is not built into every Object, but the fact that you must include it is an extra step for the programmer.
<i>With regards to ease of progamming, Ruby is the clear winner.</i>
 
===Which language makes it easier to understand code that uses reflection?===
*Reflection in Java is more difficult to understand due to required [http://en.wikipedia.org/wiki/Exception_handling exception handling]. Again, having [http://en.wikipedia.org/wiki/Exception_handling exception handling] forced upon the programmer results in extra code which could distract the reader when looking to discern the core reflection logic from the rest of the code.
<i>With regards to ease of understanding, Ruby just squeaks out ahead of Java.</i>


===Which language is more efficient with regards to Reflection?===
*The Java language implementation of reflection is more efficient than Ruby. The basis for this determination is the same point that was considered a negative for Java when it came to ease of programming: the fact that Java did not include reflection capability in the base [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html Object] class. While this might make programming reflection a bit more difficult for a Java programmer, Java programs that don't utilize reflection are more efficient since they are not carrying the extra weight of unused functionality at the top of the object hierarchy. When reflection is used in a Java program, Ruby could be considered on par with Java as far as efficiency. However the decision of the Java language designers to not force that functionality upon every Object makes the Java language's implementation of reflection more efficient.
<i>With regards to efficiency, Java comes out on top.</i>


==Java Reflection Links==
==Java Reflection Links==
Line 48: Line 112:
[http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html Using Java reflection]<br>
[http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html Using Java reflection]<br>
[http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html Javadoc for the java.lang.Class class]<br>
[http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html Javadoc for the java.lang.Class class]<br>
[http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/package-summary.html Javadoc for the java.lang.reflect package]<br>
[http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html Javadoc for the java.lang.reflect.Method class]<br>
 
[http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/package-summary.html Javadoc for the java.lang.reflect package]


==Ruby Reflection Links==
==Ruby Reflection Links==
[http://phrogz.net/programmingruby/ospace.html Good overview of reflection in Ruby]
[http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html Good overview of reflection in Ruby]<br>
[http://www.ruby-doc.org/core/classes/Object.html Rubydoc for the Object class]<br>
[http://www.ruby-doc.org/core/classes/Method.html Rubydoc for the Method class]<br>
[http://www.ruby-doc.org/core/classes/Object.html#M000610 Rubydoc for the method method of class Object]

Latest revision as of 02:35, 12 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 is 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 was implemented in both Java and Ruby. The data model in the example consists of a mountain bike class and disc brake class. A mountain bike in this example is composed of disc brakes. The mountain bike class exposes a public setter 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 a method object for the setter, 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 class is passed off as a parameter.

Note, the attr_writer feature of Ruby was intentionally not used for the sake of simplicity in keeping the two implementations as close as possible. In a Ruby only implementation, manual coding of the setter would not have been needed.

Comparison

We will now compare the sample implementations to determine which language makes it easier to program reflection, makes it easier to understand code that uses reflection, which is more efficient with regards to reflection.

Which language makes it easier to program reflection?

Reflection in Java is more difficult to write...

  • due to required exception handling. The programmer is forced to deal with the fact that the api's in Java throw exceptions. This is an issue between the two languages that affects more than just Reflection, but it still has a definite impact on how reflection is coded up.
  • since the reflection api is not built into every Object. Java requires an extra step when querying for a method, by requiring that you retrieve the an instance of a Class object first. In Ruby, you can query an object directly for a method.
  • since you have to first include the java.lang.Reflect package. This is closely related to the previous point, in that the reason that the package needs to be included is that the capability is not built into every Object, but the fact that you must include it is an extra step for the programmer.

With regards to ease of progamming, Ruby is the clear winner.

Which language makes it easier to understand code that uses reflection?

  • Reflection in Java is more difficult to understand due to required exception handling. Again, having exception handling forced upon the programmer results in extra code which could distract the reader when looking to discern the core reflection logic from the rest of the code.

With regards to ease of understanding, Ruby just squeaks out ahead of Java.

Which language is more efficient with regards to Reflection?

  • The Java language implementation of reflection is more efficient than Ruby. The basis for this determination is the same point that was considered a negative for Java when it came to ease of programming: the fact that Java did not include reflection capability in the base Object class. While this might make programming reflection a bit more difficult for a Java programmer, Java programs that don't utilize reflection are more efficient since they are not carrying the extra weight of unused functionality at the top of the object hierarchy. When reflection is used in a Java program, Ruby could be considered on par with Java as far as efficiency. However the decision of the Java language designers to not force that functionality upon every Object makes the Java language's implementation of reflection more efficient.

With regards to efficiency, Java comes out on top.

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.Method class
Javadoc for the java.lang.reflect package

Ruby Reflection Links

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