суббота, 25 февраля 2017 г.

Groovy Metaprogramming

Runtime MetaProgramming

MOP - Meta Object Protocol, набор правил, как обрабатывается системой реального времени Groovy вызов в метод объекта и как контролируется промежуточный слой в объектах.

Когда выполняется груви программа, "интерпритатор" может столнуться с тремя типами объекта, который пришел на выполнение, это:
- POJO - обычный объект Java, класс которого может быть написан на Java или любом другом языке для JVM
- POGO - объект Groovy, класс которого написан на Groovy. Он расширяет java.lang.Object и реализует groovy.lang.GroovyObject по умолчанию.
- Groovy Interceptor - объект Groovy, который реализует groovy.lang.GroovyInterceptable, этот интерфейс просто расширяет GroovyObject, не привнося никаких дополнительных деклараций, он просто говорит "интерпретатору", что все вызываемые методы должны дергать метод GroovyObject:: Object invokeMethod(String name, Object args), таким образом все вызовы перехватываются и проходят через прокси-метод класса, который мы объявили.

Содержимое GroovyObject:
package groovy.lang;

public interface GroovyObject {
    Object invokeMethod(String name, Object args);
    Object getProperty(String propertyName);
    void setProperty(String propertyName, Object newValue);
    MetaClass getMetaClass();
    void setMetaClass(MetaClass metaClass);
}

И в зависимости от типа объекта,  с которым мы имеем дело, вызов его метода может пройти по следующим цепочкам:

Обращение к пропертям состоит в том, что если мы реализуем метод getProperty, то "интерпретатор" будет всегда дергать этот метод, а уже наше ответственность обращаться ли в нем к реальному обращаемому полю объекта или нет. То же самои и с setProperty.
Обращение к реальному полю будет выглядеть так:
...
void setProperty(String name, Object value) {
  this.@"$name" = value;
}

MetaClass

Любой класс в груви имеет ассоциированный с ним метакласс, который содержит все поля и методы, класса, который он поддерживает. И динамическая природа языка выражается в том, что мы во время выполнения можем в этот метакласс добавить дополнительные поля и методы, и таким образом обеспечить класс, поддерживаемый эти мета, новыми элементами в режиме реального времени.

Categories

Иногда бывает необходимость расширить какой-то GVM класс на участок кода(определенный момент выполнения), но не хотелось бы через metaClass портить класс и потом чистить его после работы (учитывая то, что может быть параллельное выполнение). Для эго и придумали оператор  use и спецификацию категорий.
class StringCategory {
  static String shout(String str) {
    str.toUpperCase()
  }
}

use(StringCategory) {
  println "Hello, World!".shout()
}
GVM имеет уже ряд очень полезных категорий, которыми мы можем свободно пользоваться. Среди них и groovy.time.TimeCategory.

Compile Time MetaProgramming

Достигается с помощью аннотаций, который помогают не писать, а генерить по аннотации рутинный код, а также отключать например MOP режим например. 

Комментариев нет:

Отправить комментарий