CSC/ECE 517 Fall 2011/ch4 4f ss: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
Line 17: Line 17:


== Reflection in Ruby ==
== Reflection in Ruby ==
In ruby, reflection is simpler because it is done using the language mechanisms ie .methods gives the list of methods. In contrast reflection as we shall see later is much more verbose because we need to use class names,method names,parameter names etc.
Examples of reflection in ruby :
Examples of reflection in ruby :
<pre>
3.1419.methods #gives the list of methods of the float number.
irb(main):005:0> 3.1419.methods
=> [:to_s, :coerce, :-@, :+, :-, :*, :/, :quo, :fdiv, :%, :modulo, :divmod, :**,
:==, :===, :<=>, :>, :>=, :<, :<=, :eql?, :hash, :to_f, :abs, :magnitude, :zero
?, :to_i, :to_int, :floor, :ceil, :round, :truncate, :nan?, :infinite?, :finite?
, :numerator, :denominator, :to_r, :rationalize, :arg, :angle, :phase, :singleto
n_method_added, :i, :+@, :div, :remainder, :real?, :integer?, :nonzero?, :step,
:to_c, :real, :imaginary, :imag, :abs2, :rectangular, :rect, :polar, :conjugate,
:conj, :between?, :nil?, :=~, :!~, :class, :singleton_class, :clone, :dup, :ini
tialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untruste
d?, :trust, :freeze, :frozen?, :inspect, :methods, :singleton_methods, :protecte
d_methods, :private_methods, :public_methods, :instance_variables, :instance_var
iable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :
kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?,
:extend, :display, :method, :public_method, :define_singleton_method, :__id__,
:object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exe
c, :__send__]
</pre> This is an example of discovering things about 3.1459 at runtime.(Reflection).We can act on information during runtime without compiling it in. Information needed can be found out at run-time instead of writing code at compile time.
<pre>puts "hello".class  #returns the class of object "hello" </pre>
<pre>puts "hello".class  #returns the class of object "hello" </pre>


Line 38: Line 59:
</pre>
</pre>


Obtaining Reference to a
MetaProgramming :
 
 
The greek prefix 'Meta' refers to knowledge about knowledge. Metaprogramming means programs can create new code at runtime and run the code that is written. Program that writes a program.The related technique of metaprogramming allows one to create new program entities, such as methods or classes, at run time. 
<pre>
puts 100.class # print the class of 1
>> Fixnum
puts 98343098452405890454.class #prints the class of 98343098452405890454
>> Bignum
puts 123456789012345.kind_of? Integer
>> true
puts 123456789012345.instance_of? Integer
>> false
puts 123456789012345.instance_of? Bignum
>> true
</pre>
 
Difference between Fixnum and Bignum in Ruby :
 
 
A Fixnum stores Integer values which can be represented in a native machine word (minus 1 bit). If an operation on a Fixnum results in a value that exceeds the range, the value is automatically converted to a Bignum.
 
When Fixnum objects  are assigned or passed as parameters, the actual objects are passed, rather than  references to the objects. There is  only one Fixnum object instance for a given integer value
 
Bignum objects are used to store values of integers outside the range of Fixnum. They are created automatically when encountered with integer calculations that would otherwise overflow a Fixnum. When a calculation involving Bignum objects returns a result that will fit in a Fixnum, the result is automatically converted.
 
OO Languages distinguish between a primitive and reference with help of a  leading or trailing bit. ie One bit indicates if the remaining bits store a primitive or a reference and the remaining bits represent the value. In numeric  calculations, most of numbers are primitives so primitives can be used directly avoiding the overhead of indirection. One main difference between Fixnum and Bignum is that Fixnum can be stored in 1 machine word. If the object cannot be stored in a machine word then Bignum is used. In case of Bignum a reference to the actual object is stored.
 
In contrast to Fixnum objects, in case of objects references to objects are used for parameter passing.
 
 
'''Obtaining Reference to a method in ruby:'''
 
A reference to a method can be obtained by  using the method ''method'' in the class ''Object''.
It is available to all classes, since Object is the superclass of all classes.  The reference thus obtained  can be used to invoke that particular method.
eg:
<pre>
str = "Hello, World"
#The name of the method has to be passed as a symbol to method:
m = str.method(:upcase) # returns a Method object which is  a closure.
puts m.call
</pre>
Note that in the above example name of the method passed as a symbol.Every instance of a particular symbol is the same symbol. Every instance of a particular symbol is the same symbol.
 
<pre>
irb(main):009:0> puts :mysymbol.object_id
332648
=> nil
irb(main):010:0> puts :mysymbol.object_id #Note that 2 occurrences of the same symbol yielded
332648                                    #same object id unlike strings (shown below)
=> nil
irb(main):011:0> puts "mystring".object_id
21196488
=> nil
irb(main):012:0> puts "mystring".object_id
20959140
 
</pre>
 
application of passing methods as parameters :Quadrature integration
Suppose we need to compute the area under a curve described by some function, e.g., x2 + 2x + 3.
 
Then we can define
class Float
  def poly
    self*self + 2*self + 3
  end
end
And to compute the area,we  pass poly to an integration method which takes the method reference,upper bound and lower bound between which the area is to be computed as the parameters
area = integrate(:poly, 10, 20) #calculates the area of the curve x2+2x+3 between the limits x=10 to x=20.
 
 
'''
Intercepting calls to undefined methods'''
Ruby provides an option to intercept the call when a call to an undefined method is made on an object.
Implementation of  the method method_missing within the class definition provides this facility.  Ruby passes as parameters the name of the method called and the arguments passed to it.
class Duck
  def quack
    puts "Quack"
  end 
  def method_missing(meth, *args)
    puts "Sorry, I do not #{meth}"
  end
end
d = Duck.new
d.quack
>>Quack
d.bark
>> Sorry, I do not bark
 
 
Example of an interesting usage of method_missing: “Roman method_missing”.
 


== Reflection in Java ==
== Reflection in Java ==
Line 270: Line 384:
* Reflection helps in keeping software  [http://www.linfo.org/robust.html robust]
* Reflection helps in keeping software  [http://www.linfo.org/robust.html robust]
* It helps in making the applications more flexible,extensible and pluggable.
* It helps in making the applications more flexible,extensible and pluggable.
* It helps in making the source code more readable.
* It helps in making the source code more readable and easier to understand.
* It can simplify source code and design.
* It can simplify source code and design.
* Expensive conditional code can be reduced/removed.
* Expensive conditional code can be reduced/removed.

Revision as of 04:21, 19 October 2011

Reflection

Reflection allows program entities to discover things about themselves through introspection.

In other words,Reflection is the ability of a program to determine information about an object at runtime.

The information may include the following :

  • The type of the object
  • Inheritance structure
  • Methods it contains.
  • Number of parameters of the methods,types of parameters, return types.
  • Names and types of the attributes of the object.

Reflection is supported by many Object-oriented programminglanguages in various forms. Powerful and flexible reflection mechanisms are exhibited by Smalltalk, [1], and Python . Java also supports reflection. But reflection in java is verbose and is not as flexible and dynamic as these languages. C++ allows a program to determine the type of an object at run-time. Thus it does support reflection but in a limited form only. Eiffel also has support for a limited form of reflection which includes the ability to determine the features contained in an object.

Reflection in Ruby

In ruby, reflection is simpler because it is done using the language mechanisms ie .methods gives the list of methods. In contrast reflection as we shall see later is much more verbose because we need to use class names,method names,parameter names etc. Examples of reflection in ruby :

3.1419.methods #gives the list of methods of the float number.
irb(main):005:0> 3.1419.methods
=> [:to_s, :coerce, :-@, :+, :-, :*, :/, :quo, :fdiv, :%, :modulo, :divmod, :**,
 :==, :===, :<=>, :>, :>=, :<, :<=, :eql?, :hash, :to_f, :abs, :magnitude, :zero
?, :to_i, :to_int, :floor, :ceil, :round, :truncate, :nan?, :infinite?, :finite?
, :numerator, :denominator, :to_r, :rationalize, :arg, :angle, :phase, :singleto
n_method_added, :i, :+@, :div, :remainder, :real?, :integer?, :nonzero?, :step,
:to_c, :real, :imaginary, :imag, :abs2, :rectangular, :rect, :polar, :conjugate,
 :conj, :between?, :nil?, :=~, :!~, :class, :singleton_class, :clone, :dup, :ini
tialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untruste
d?, :trust, :freeze, :frozen?, :inspect, :methods, :singleton_methods, :protecte
d_methods, :private_methods, :public_methods, :instance_variables, :instance_var
iable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :
kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?,
 :extend, :display, :method, :public_method, :define_singleton_method, :__id__,
:object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exe
c, :__send__]

This is an example of discovering things about 3.1459 at runtime.(Reflection).We can act on information during runtime without compiling it in. Information needed can be found out at run-time instead of writing code at compile time.

puts "hello".class  #returns the class of object "hello" 

Output:

String


puts "hello".class.superclass  #returns the superclass of the String class

Output:

Object
puts string.ancestors #returns the ancestors of the string class

String

Comparable Object Basic Object Kernel

MetaProgramming :


The greek prefix 'Meta' refers to knowledge about knowledge. Metaprogramming means programs can create new code at runtime and run the code that is written. Program that writes a program.The related technique of metaprogramming allows one to create new program entities, such as methods or classes, at run time.

puts 100.class # print the class of 1
>> Fixnum
puts 98343098452405890454.class #prints the class of 98343098452405890454
>> Bignum
puts 123456789012345.kind_of? Integer
>> true
puts 123456789012345.instance_of? Integer
>> false
puts 123456789012345.instance_of? Bignum
>> true

Difference between Fixnum and Bignum in Ruby :


A Fixnum stores Integer values which can be represented in a native machine word (minus 1 bit). If an operation on a Fixnum results in a value that exceeds the range, the value is automatically converted to a Bignum.

When Fixnum objects are assigned or passed as parameters, the actual objects are passed, rather than references to the objects. There is only one Fixnum object instance for a given integer value

Bignum objects are used to store values of integers outside the range of Fixnum. They are created automatically when encountered with integer calculations that would otherwise overflow a Fixnum. When a calculation involving Bignum objects returns a result that will fit in a Fixnum, the result is automatically converted.

OO Languages distinguish between a primitive and reference with help of a leading or trailing bit. ie One bit indicates if the remaining bits store a primitive or a reference and the remaining bits represent the value. In numeric calculations, most of numbers are primitives so primitives can be used directly avoiding the overhead of indirection. One main difference between Fixnum and Bignum is that Fixnum can be stored in 1 machine word. If the object cannot be stored in a machine word then Bignum is used. In case of Bignum a reference to the actual object is stored.

In contrast to Fixnum objects, in case of objects references to objects are used for parameter passing.


Obtaining Reference to a method in ruby:


A reference to a method can be obtained by using the method method in the class Object. It is available to all classes, since Object is the superclass of all classes. The reference thus obtained can be used to invoke that particular method. eg:

str = "Hello, World"
#The name of the method has to be passed as a symbol to method:
m = str.method(:upcase) # returns a Method object which is  a closure.
puts m.call
Note that in the above example name of the method passed as a symbol.Every instance of a particular symbol is the same symbol. Every instance of a particular symbol is the same symbol.
irb(main):009:0> puts :mysymbol.object_id
332648
=> nil
irb(main):010:0> puts :mysymbol.object_id #Note that 2 occurrences of the same symbol yielded 
332648                                    #same object id unlike strings (shown below)
=> nil
irb(main):011:0> puts "mystring".object_id
21196488
=> nil
irb(main):012:0> puts "mystring".object_id
20959140

application of passing methods as parameters :Quadrature integration Suppose we need to compute the area under a curve described by some function, e.g., x2 + 2x + 3.

Then we can define class Float

 def poly
   self*self + 2*self + 3
 end

end And to compute the area,we pass poly to an integration method which takes the method reference,upper bound and lower bound between which the area is to be computed as the parameters area = integrate(:poly, 10, 20) #calculates the area of the curve x2+2x+3 between the limits x=10 to x=20.


Intercepting calls to undefined methods Ruby provides an option to intercept the call when a call to an undefined method is made on an object.

Implementation of  the method method_missing within the class definition provides this facility.  Ruby passes as parameters the name of the method called and the arguments passed to it. 

class Duck

 def quack
   puts "Quack"
 end  
 def method_missing(meth, *args)
   puts "Sorry, I do not #{meth}"
 end

end d = Duck.new d.quack >>Quack d.bark >> Sorry, I do not bark


Example of an interesting usage of method_missing: “Roman method_missing”.


Reflection in Java

Reflection in Java is much more verbose than in ruby.It is an advanced feature of the Java environment. Reflection is achieved using the Reflection API.The verbosity of reflection in java may be associated with the usage of the library for reflection.

Big industrial-strength protocols like SOAP and JavaBeans wouldn't be possible if it weren't for Reflection. Every time you drag-and-drop an object in your favorite IDE into a form, Reflection is orchestrating the action behind the scenes. Actually, most sophisticated Java applications rely on Reflection in one way or another.

Reflection is an advanced feature of the Java environment. It gives runtime information about objects, classes, and interfaces. Some of the questions that can be answered using reflection in java:


*   Which class does an object belong to?
*   What is the description of a given class name?
*   What are the fields in a given class?
*   What is the type of a field?
*   What are the methods in a class?
*   What are the parameters of a method?
*   What are the constructors of a given class? 
*   Constructing an object using a given constructor
*   Invoking an object's method using such-and-such parameters
*   Assigning a value to an object's field
*   Dynamically creating and manipulating arrays  

Java Reflection Classes


All Reflection classes (With the exception of the class Class that resides in the default Java package) are contained in the package java.lang.reflect.

Following are some of the classes used to various represent members of a class.: Classes-'Class' class Fields-'Field' class methods-'Method' class constructors-'Constructor' class arrays-'Array' class.

Illustration of Reflection in Java through Examples


Class


Each class or interface in Java is described by a Class object.It contains methods to obtain details about the class like name, parent class, constructors, fields, methods, interfaces implemented etc.

To obtain the class that an object belongs to, invoke the method Class getClass()(returns 'Class') of the 'Object' class (superclass of all the Java classes hierarchy)

String myStr = "HelloWorld";
Class theClass = myStr.getClass(); // 'theClass' now contains 'String'


The property ".class"(available for every java class) returns a Class object for the class.

String myStr = "HelloWorld";
if (myStr.getClass()==String.class)
System.out.println("The object is a String"); // prints "The object is a String"

The wrapper classes (Integer, Boolean, Double,...) contain a ".TYPE" property that returns the Class object representing the primitive type.

Class myClass = Integer.TYPE; //

Field


The Field class describes the different attributes of a Java class field. Information such as a field name, its type, and its accessibility can be obtained from a field object. It also contains methods to set and get the field's value for a given object Example


   import java.lang.reflect.*;
        
   public class MyfieldClass {
      int i = 100;
      String s = "Hello World";
        
      public static void main(String args[])
      {
         try {
            Class cls = Class.forName("MyfieldClass");
        
            Field flist[]= cls.getDeclaredFields();
            for (int i = 0; i < flist.length; i++) {
              
               Field f = flist[i];
               System.out.println("name
                  = " + f.getName());
               System.out.println("decl class = " +
                           f.getDeclaringClass());
               System.out.println("type
                  = " + f.getType());
               
            }
          }
          catch (Throwable e) {
             System.err.println(e);
          }
       }
   }

The output of the program is:
  name = i
   decl class = MyfieldClass
   type = double
   
   name = s
   decl class = MyfieldClass
   type = class java.lang.String
   
  

Method


The Method class is used to obtain information(the method name, its type, its accessibility, and its parameter types) about class methods.We can even invoke the method on a particular object and pass a set of parameters to it.

   import java.lang.reflect.*;

   public class myMethodClass {
      private int myMethod(int y, int x) 
      {
         return x+y;
      }
        
      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("myMethodClass");
        
            Method mlist[] = cls.getDeclaredMethods();
            
              for (int i = 0; i < mlist.length;i++) 
              {  
               Method m = mlist[i];
               System.out.println("name= " + m.getName());
               System.out.println("decl class = " +m.getDeclaringClass());
                              
               Class pt[] = m.getParameterTypes();
               for (int j = 0; j < pt.length; j++)
                  System.out.println("param #" + j + " " + pt[j]);
                   
              
               System.out.println("return type = " +
                                  m.getReturnType());
               
            }
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

The output of the program is:

  name = myMethod
   decl class = class myMethodClass
   param #0 int
   param #1 int
   
   return type = int
   
   name = main
   decl class = class myMethodClass
   param #0 class [Ljava.lang.String;
   return type = void
   


Constructor


The Constructor class can be used to obtain information(parameter types, number of parameters, and accessibility) about class constructors.We can also invoke the constructor to create new object instances

 import java.lang.reflect.*;
        
   public class Myconstructor {
      public Myconstructor()
      {
      }
        
     public static void main(String args[])
      {
         try {
           Class c = Class.forName("Myconstructor");
        
           Constructor clist[]= c.getDeclaredConstructors();
         
           for (int i = 0; i < clist.length; i++) {
               Constructor ct = clist[i];
               System.out.println("name= " + ct.getName());
               System.out.println("Declaring Class Name = " +
                            ct.getDeclaringClass());
               Class pTypes[] = ct.getParameterTypes();
               for (int j = 0; j <  pTypes.length; j++)
                  System.out.println("param #" 
                     + j + " " +  pTypes[j]);
               
              
            }
          }
          catch (Throwable e) {
             System.err.println(e);
          }
      }
   }

output:

Name=MyConstructor
Declaring Class name=MyConstructor


Applications of Reflection in Java:Many sophisticated Java applications rely on reflection

  • Reflection is used extensively in protocols like SOAP
  • Whenever we drag-and-drop an object in an IDE to use it in a form, Reflection is used behind the scenes.
  • Java Beans
  • It is used in Debuggers and Test Tools which require examining the private members <ref>http://download.oracle.com/javase/tutorial/reflect/</ref>.
  • It is used class browser which needs to be able to enumerate the members of classes.
  • It is also employed in Visual development environments. The type information available in reflection is used to help the developer in writing correct code.


Benefits

  • Reflection helps in keeping software robust
  • It helps in making the applications more flexible,extensible and pluggable.
  • It helps in making the source code more readable and easier to understand.
  • It can simplify source code and design.
  • Expensive conditional code can be reduced/removed.


See more: http://download.oracle.com/javase/tutorial/reflect/