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