Groovy - 元对象编程



元对象编程或 MOP 可用于动态调用方法,以及动态创建类和方法。

那么这意味着什么呢?让我们考虑一个名为 Student 的类,它是一个没有任何成员变量或方法的空类。假设您必须对这个类调用以下语句。

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

现在在元对象编程中,即使该类没有 Name 成员变量或 Display() 方法,上述代码仍然可以工作。

这怎么可能呢?为了实现这一点,必须实现 GroovyInterceptable 接口以挂接到 Groovy 的执行过程中。以下是此接口提供的方法。

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) 
}

因此,在上述接口描述中,假设您必须实现 invokeMethod(),它将被调用用于每个存在或不存在的方法。

缺少属性

那么让我们来看一个如何为缺少的属性实现元对象编程的示例。以下代码需要注意以下关键事项。

  • Student 类没有定义名为 Name 或 ID 的成员变量。

  • Student 类实现了 GroovyInterceptable 接口。

  • 有一个名为 dynamicProps 的参数,它将用于保存动态创建的成员变量的值。

  • 已实现 getproperty 和 setproperty 方法以在运行时获取和设置类属性的值。

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]
   } 
} 

以下代码的输出将是:

Joe 
1

缺少方法

那么让我们来看一个如何为缺少的属性实现元对象编程的示例。以下代码需要注意以下关键事项:

  • Student 类现在实现了 invokeMethod 方法,无论方法是否存在都会调用该方法。

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"
   }
}

以下显示了以下代码的输出。请注意,即使 Display 方法不存在,也没有缺少方法异常错误。

Joe 
1 

元类

此功能与 MetaClass 实现相关。在默认实现中,您可以访问字段而无需调用它们的 getter 和 setter。以下示例展示了如何通过使用 metaClass 函数来更改类中私有变量的值。

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;
   } 
}

以下代码的输出将是:

Joe 
Mark

方法缺失

Groovy 支持 methodMissing 的概念。此方法与 invokeMethod 的区别在于,它仅在方法调度失败时调用,即当找不到给定名称和/或给定参数的方法时。以下示例展示了如何使用 methodMissing。

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"
   }  
}

以下代码的输出将是:

Joe 
1 
Missing method 
广告