На информационном ресурсе применяются рекомендательные технологии (информационные технологии предоставления информации на основе сбора, систематизации и анализа сведений, относящихся к предпочтениям пользователей сети "Интернет", находящихся на территории Российской Федерации)

Динамика Groovy

В этой заметке я расскажу о некоторых возможностях Groovy, которые обеспечивают его динамичность. В частности:

  • Метаклассы
  • Перехват вызова методов
  • Категории

 

Получение списков свойств и методов класса

У каждого объекта есть методы properties и methods, которые возвращают отображения для свойств и методов объекта соответственно.


В частности, следующий код распечатывает все свойства и методы объекта:

obj.properties.each{ println it } // Распечатываем свойства
obj.methods.each{ println it } // А теперь методы

Доступ к свойствам и методам через GString

Рассмотрим задачу доступа к полю или методу, имя которого становится известно только в момент выполнения. В Java для этого приходится использовать достаточно недобный механизм Reflection. В Groovy для этой задачи может быть использован GString. В частности, справа от оператора “.” может находится экземпляр строки, значение которой будет использоваться для доступа к свойству или методу объекта. Например:

class Person { // Объявляем новый класс
String name; // Объявляем свойство в классе
}
 
def p = new Person()
def fn = 'name' // Имя свойства
p."$fn" = 'alex' // Записываем в свойство новое значение

Метаклассы

 

Динамичность языка Groovy обеспечивается особым механизмом вызова методов: при вызове метода проверяется не только его наличие в классе, но и в специальном объекте, называемом метаклассом. При этом, при первом доступе к свойству metaClass объекта, его метакласс замещается специальным, представляющим из себя Expando, о котором я писал ранее.

К метаклассу объекта можно получить доступ через поле metaClass объекта.

Используя эту особенность, можно добавлять методоы к уже определенным ранее классам. Для этого всего-навсего необходимо определить соответствующий метод в ExpandoMetaClass класса.

Например, можно определить новый метод для всех объектов класса String:

String.metaClass.sizeSqr = {
delegate.size * delegate.size
}

Перехват вызова методов

 

Особенностью многих динамических языков является возможность вызова “несуществующих” методов, которые перехватываются специальным обработчиком. Groovy также не является исключением:

Любой класс может реализовать интерфейс GroovyInterceptable и определить метод invokeMethod, который будет вызываться при любом вызове метода. Например:

class Service {
 
def invokeMethod( String method, args ) {
println "Called $method"
}
}
 
s = new Service()
s.doSomething() // Будет напечатано "Called doSomething"

Второй вариант перехвата методов - добавление метода invokeMethod в метакласс объекта.

Категории

 

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

Категория в Groovy - это класс, содержащий статические методы, расширяющие другие классы. Например, рассмотрим класс:

class PersistenceCategory {
 
static void save( Object o ) {
// Реализация сохранения объекта
}
 
static void load( Object o ) {
// Реализация загрузки объекта
}
}

Если его использовать в качестве категории, все объекты в блоке получат методы save и load. Для использования категорий Groovy содержит ключевое слово use. Например:

use( PersistenceCategory ) {
someObject.load(); // Вызывается PersistenceCategory.save( someObject );
...
someObject.save(); // PersistenceCategory.load( someObject );
}
Рекомендуем
Популярное
наверх