Groovy - Meta Object Programming



Meta object programming or MOP can be used to invoke methods dynamically and also create classes and methods on the fly.

So what does this mean? Let’s consider a class called Student, which is kind of an empty class with no member variables or methods. Suppose if you had to invoke the following statements on this class.

Def myStudent = new Student() 
myStudent.Name = ”Joe”; 
myStudent.Display()

Now in meta object programming, even though the class does not have the member variable Name or the method Display(), the above code will still work.

How can this work? Well, for this to work out, one has to implement the GroovyInterceptable interface to hook into the execution process of Groovy. Following are the methods available for this interface.

Public interface GroovyInterceptable { 
   Public object invokeMethod(String methodName, Object args) 
   Public object getproperty(String propertyName) 
   Public object setProperty(String propertyName, Object newValue) 
   Public MetaClass getMetaClass() 
   Public void setMetaClass(MetaClass metaClass) 
}

So in the above interface description, suppose if you had to implement the invokeMethod(), it would be called for every method which either exists or does not exist.

Missing Properties

So let’s look an example of how we can implement Meta Object Programming for missing Properties. The following keys things should be noted about the following code.

  • The class Student has no member variable called Name or ID defined.

  • The class Student implements the GroovyInterceptable interface.

  • There is a parameter called dynamicProps which will be used to hold the value of the member variables which are created on the fly.

  • The methods getproperty and setproperty have been implemented to get and set the values of the property’s of the class at runtime.

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      mst.Name = "Joe";
      mst.ID = 1;
		
      println(mst.Name);
      println(mst.ID);
   }
}

class Student implements GroovyInterceptable { 
   protected dynamicProps=[:]
	
   void setProperty(String pName,val) {
      dynamicProps[pName] = val
   }
   
   def getProperty(String pName) {
      dynamicProps[pName]
   } 
} 

The output of the following code would be −

Joe 
1

Missing methods

So let’s look an example of how we can implement Meta Object Programming for missing Properties. The following keys things should be noted about the following code −

  • The class Student now implememts the invokeMethod method which gets called irrespective of whether the method exists or not.

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      mst.Name = "Joe";
      mst.ID = 1;
		
      println(mst.Name);
      println(mst.ID);
      mst.AddMarks();
   } 
}
 
class Student implements GroovyInterceptable {
   protected dynamicProps = [:]  
    
   void setProperty(String pName, val) {
      dynamicProps[pName] = val
   } 
   
   def getProperty(String pName) {
      dynamicProps[pName]
   }
   
   def invokeMethod(String name, Object args) {
      return "called invokeMethod $name $args"
   }
}

The output of the following codewould be shown below. Note that there is no error of missing Method Exception even though the method Display does not exist.

Joe 
1 

Metaclass

This functionality is related to the MetaClass implementation. In the default implementation you can access fields without invoking their getters and setters. The following example shows how by using the metaClass function we are able to change the value of the private variables in the class.

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      println mst.getName()
      mst.metaClass.setAttribute(mst, 'name', 'Mark')
      println mst.getName()
   } 
} 

class Student {
   private String name = "Joe";
	
   public String getName() {
      return this.name;
   } 
}

The output of the following code would be −

Joe 
Mark

Method Missing

Groovy supports the concept of methodMissing. This method differs from invokeMethod in that it is only invoked in case of a failed method dispatch, when no method can be found for the given name and/or the given arguments. The following example shows how the methodMissing can be used.

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      mst.Name = "Joe";
      mst.ID = 1;
		
      println(mst.Name);
      println(mst.ID);
      mst.AddMarks();
   } 
} 

class Student implements GroovyInterceptable {
   protected dynamicProps = [:]  
    
   void setProperty(String pName, val) {
      dynamicProps[pName] = val
   }
   
   def getProperty(String pName) {
      dynamicProps[pName]
   }
   
   def methodMissing(String name, def args) {         
      println "Missing method"
   }  
}

The output of the following code would be −

Joe 
1 
Missing method 
Advertisements