CSC/ECE 517 Fall 2010/ch2 S24 NS

From Expertiza_Wiki
Jump to navigation Jump to search

Metaprogramming in statically typed languages

What is Metaprogramming?

Metaprogramming is the technique that allows us to write programs that can manipulate other programs or themselves as a part of their data. Such programs help the programmer to avoid recompilations by executing their part of the work at compile time rather than at runtime.

The ability of a program to treat itself as a part of the data is known as reflection by virtue of which the program can modify its own structure and behavior. Often, metaprogramming and reflection are synonymous terms and one can be defined in the context of the other. Metalanguage is the language in which the metaprogram is written.

A most illustrative instance of metaprogramming is the use of Vectors in many languages, which are a set of multidimensional mathematical entities. Through metaprogramming, we can pass parameters to a generic class, the code for which will be generated by the compiler for each dimension of the Vector.

Example of Metaprogramming

The following figure applies the concept of Metaprogramming to the Ruby programming language

The attributes of the File entity are redefined and modified at runtime using the expressions of the programming language.

Now let us take another aspect of Metaprogramming in the same ruby language. Supposing we are having the following code in our ruby file.

       COLORS = { :black   => "000",
     	:red 	=> "f00",
     	:green   => "0f0",
     	:yellow  => "ff0",
     	:blue	=> "00f",
     	:magenta => "f0f",
     	:cyan	=> "0ff",
     	:white   => "fff" 
        }

The class can be defined as

       class String
       COLORS.each do |color,code|
       define_method "in_#{color}" do "#{self}"
       end
       end
       end                                   
                                  	

         	          

The above code generates new methods for the build in String class based on a list of colors and they wrap the particular String in the respective color by virtue of HTML tags.

In particular, we can use this code in our application as :

                           	“ ’ Hello World’.in_blue”

which will print the text in blue color. This aspect of metaprogramming saves the programmer the tedious job of encoding each behavior in a type of method.

Metaprogramming in Java:

Metaprogramming in java comprises of three main components:

  • Reflection
  • Generics
  • Annotations

Reflection in Java

The reflective nature of a Java program allows Java programs to introspect upon themselves and manipulate internal properties of the program. One tangible use of this feature is in JavaBeans in which a information about the classes are dynamically obtained via a Builder Tool as the classes are dynamically loaded. Reflection in Java is normally accomplished through the Reflection API which consists of the "Reflect" package and is available in the java.lang hierarchy.

Consider the following code


  import java.lang.reflect.*;
  public class DumpMethods {
 	public static void main(String args[])
 	{
    	try {
       	Class c = Class.forName(args[0]);
       	Method m[] = c.getDeclaredMethods();
       	for (int i = 0; i < m.length; i++)
       	System.out.println(m[i].toString());
    	}
    	catch (Throwable e) {
       	System.err.println(e);
    	}
 	}
                            	                 

If it is invoked in the following manner

        “java DumpMethods java.util.Stack”

The output will be:

      public java.lang.Object java.util.Stack.push(
      java.lang.Object)
      public synchronized
      java.lang.Object java.util.Stack.pop()
        public synchronized
 	java.lang.Object java.util.Stack.peek()
         public boolean java.util.Stack.empty()
         public synchronized
	   int java.util.Stack.search(java.lang.Object) 
                                	
                 	                 


The method names of java.util.Stack class are listed with their parameters and return types

  • Class.forName : It is a static method of Class that loads the specific class which, in this case, is the java.util.Stack class
  • getDeclaredMethods: It is another method of Class that retrieves the list of methods and return them as objects defined in the Stack class
  • Method: Method is another class of which an array of objects is created to hold the values of the returned objects

Generics in Java

Generic programming is a type of computer programming in which the algorithms are written to accommodate data types whose values are to be specified late. Such data types are instantiated only when the particular datatype is passed as a parameter to the Generic class.

In Java, code is not created for each type specific instance of a Generic like other statically typed languages like C++. Bytecode is generated only once for each function and class and the generic types are replaced by “Object”, which is a built in generic type.

How Generics are defined?

Consider the use of the List class to define generics. Then, it can be defined as

                	List <WrapperClass type> object = new ArrayList <WrapperClass type>

Wrapper Class may be String or Integer or similar class types based on the requirement

An example of the use of Generics is as follows

     import java.util.*;
     public class BoxingGenericsExample {
      public static void main(String args[])
       {
       HashMap<String,Integer> hm = new HashMap<String,Integer>();
       hm.put("speed", 20);
      }
     }
                                  

The HashMap can accommodate two values of String and Integer types which are declared using Generics

Generic Classes

It is possible to define classes in Generics

   class GenericExample<T> {
    T ob; // declare an object of type T
     GenericExample(T o) //constructor initializing the object of T to the object passed as args  
    {        
   ob = o;
     }
    T getob() {
     return ob;
     }
    void showType() {
      System.out.println("Type of T is " + ob.getClass().getName());
      }
      }
     public class GenDemo {
      public static void main(String args[]) {
       GenericExample<Integer> iOb= new GenericExample<Integer>(88);
       iOb.showType();
        }}
           	             

At runtime the value of T will be the Integer class

Generic Interfaces and Methods

Similarly it is also possible to define interfaces and methods in Generics

   public interface List<E> {
       void add(Ex);
        void display();
       }


    //Generic Method
    public static <T> void filter()
     {
       //Method code
      }
        

The main disadvantages of Generics are that parameter type information is not available at run time, and that automatically generated casts may fail when interoperating with ill-behaved legacy code so runtime safety is compromised.

Annotations in Java

Annotations are syntactic metadata which can be added to the java source code and can include classes, methods, variables and packages. This is another manifestation of the reflective nature of Java in which such annotations may be embedded in class files and retrieved at runtime. An annotation definition might look like this

public @interface TestAnnotation
   	{
          	// Property Definition here.
   	}

‘@’ indicates the start of an annotation definition. The above annotation is an interface level annotation. This is specified in the declaration of an annotation itself and is known as “Annotating an Annotation” The compiler has a reserved set of annotations for syntactic purposes among which three are worth mentioning

@Deprecated

The annotated element is deprecated and no longer in use.

    //Example of  a deprecated annotation
    @Deprecated
    static void deprecatedMethod()
    {
      //code
     }

@Override

The annotated element is meant to be overridden in the superclass

    //Example of a override annotation
    @Override
    int overriddenMethod() 
    {
     //code }

@SuppressWarnings

The compiler has to suppress warnings which it would otherwise generate. This is usually done when a deprecated method is used and warnings from the compiler are not desired.

   //Example of a suppress warning annotation  
    // compiler not to generate a warning
     @SuppressWarnings("deprecation")
     void useDeprecatedMethod() {
     objectOne.deprecatedMethod(); //deprecation warning - suppressed
     }

Technical issues: Meta Programming with JAVA

Every time a user wishes to write a Java Bean object, following key steps should be implemented. This includes:

  • Making the class serializable
  • Ensuring the class has a default constructor
  • Writing getters and/or setters for all properties
  • Writing methods to register and unregister listeners for the bound properties

Unit tests are seldom written for getters and setters and generally the process is error prone. These shortcomings are overcome by code generating tools like XDoclet and Eclipse but they have their own limitations.All these tools use their own template language and their functionality is restricted to the behaviour of C/C++ macros. In a metaprogramming language, the template and the code it generates are implemented in one language only. It is therefore possible to extend the language itself, by adding new constructs, rather than developing the object hierarchy.

How to resolve this problem?

Attribute oriented programming

It is a program-level marking technique to be exploited to enable meta programming and address the challenges posed by it. Programmers can mark elements like classes and methods to indicate that they maintain application-specific or domain-specific semantics. Application's business logic is separated from domain specific semantics using attributes. By keeping the implementation details of those semantics from program code hidden, attributes increase the level of abstraction and reduce programming complexity. This results in simpler and more readable programs. The program elements associated with attributes are transformed to more detailed programs by a supporting tool. A supporting tool can be a preprocessor.

XDoclet

Users can add more meaning to the code by adding meta data to the java source code in special JavaDoc tags. This technique, also referred as Attribute Oriented Programming, is made possible in Java by XDoclet, an open source code generation engine. XDoclet works by parsing the source file and generating several artifacts from it. Artifacts can include XML descriptors and/or source code. Using the information provided in the source code and in its JavaDoc tags, template generate these files. XDoclet includes a core module and constantly growing number of modules. Whenever there is a requirement for a new component, new modules can be written easily using this feature. XDoclet has several advantages that has made it an instant hit with the programming community. A few advantages are

  • Redundancy elimination: Users need to write only the business logic and XDoclet generates the support code and “boiler-plate” for it.
  • Extensibility: XDoclet is designed for modular programming. On identifying repeatable code, users can write XDoclet templates to generate the necessary code.
  • Better understanding of J2EE programs: Users need to implement the enterprise bean and XDoclet generates the necessary interfaces, value objects, struts for the user.

XDoclet was initially conceived as tool for creating EJBs. Over the course of time, it has evolved into a code generation engine making programming a lot easier.

     public class Matrix 
     {
     /** @todo need to handle the case where there is no spoon */
     public void reload() {
     // …   }}

Now to use the XDoclet code we have to insert a todo tag in the Ant Build file like the following

    <target name="todo"
    depends="init">
    <documentdoclet destdir="todo">
    <fileset dir="${dir.src}">
    <include name="**/*.java" />
                                    

Prior to the release of the Metadata Facility, XDoclet was used for attribute oriented programming approach in Java.

Metadata Facility

An advanced and a sophisticated technique for Attribute Oriented Programming in Java is through the Metadata Facility (JSR-175) [14] which is included in the J2SE version 5.0. It is actually an API (Application Programming Interface) for enabling annotations of fields, methods and classes and thus enabling developement tools and runtime libraries to run them in a specific desired way.

References

[1] Lindegren, Patrik and Ostlund, Joakim, Metaprogramming in Java, C# and C++, 24th May, 2006

[2] Metaprogramming in Ruby, Retrieved September 21st , 2010, from Wikipedia page: http://en.wikipedia.org/wiki/Ruby_(programming_language)#Metaprogramming

[3] Attribute Oriented Programming, Retrieved September 21st, 2010, from the Wikipedia page :http://en.wikipedia.org/wiki/Attribute-Oriented_Programming

[4] Generics, Retrieved September 21st, 2010, from the Oracle Homepage:http://download.oracle.com/javase/1.5.0/docs/guide/language/generics.html

[5] Venkat Subramaniam, Generics in Java – Part I, from the AgileDeveloper Site : http://agiledeveloper.com/articles/GenericsInJavaPartI.pdf

[7] Java Tutorials, Retrieved September 21st, 2010, from the Java Homepage: http://download.oracle.com/javase/tutorial/java/

[8] Using Java Reflection, Retrieved September 21st, 2010, from the Oracle Homepage: http://java.sun.com/developer/technicalArticles/ALT/Reflection/

[9] Java Annotations, Retrieved September 21st, 2010, from Javabeat Homepage: http://www.javabeat.net/articles/30-annotations-in-java-50-1.html

[10] XDoclet: What is XDoclet, Retrieved September 21st, 2010, from the SourceForge Website: http://xdoclet.sourceforge.net/xdoclet/index.html