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の実装に関連しています。デフォルトの実装では、ゲッターとセッターを呼び出さずにフィールドにアクセスできます。次の例は、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