Запутался в методе invokeMethod в Groovy MOP

Сначала взгляните на следующий код Groovy:

class Car {

    def check() { System.out.println "check called..." }

    def start() { System.out.println "start called..." }

}

Car.metaClass.invokeMethod = { String name, args ->

    System.out.print("Call to $name intercepted... ")

    if (name != 'check') {
        System.out.print("running filter... ")
        Car.metaClass.getMetaMethod('check').invoke(delegate, null)
    }

    def validMethod = Car.metaClass.getMetaMethod(name, args)
    if (validMethod != null) {
        validMethod.invoke(delegate, args)
    } else {
        Car.metaClass.invokeMissingMethod(delegate, name, args)
    }
}

car = new Car()
car.start()

Результат:

Call to start intercepted... running filter... check called...
start called...

В соответствии с механизмом диспетчеризации методов Groovy я думаю, что метод запуска в автомобиле должен вызываться напрямую, а не перехватываться с помощью invokeMethod в метаклассе автомобиля. Почему метод запуска перехватывается методом invokeMethod? Как вызывается метод invokeMethod при вызове метода для объекта?

Если вы можете дать мне несколько подробных объяснений о механизме диспетчеризации методов Groovy (MOP), я буду признателен.


person Samuel Gong    schedule 15.06.2015    source источник


Ответы (1)


Короче говоря, вы не используете стандартный метакласс, поэтому вы не получаете стандартный Groovy MOP.

Car.metaClass.invokeMethod = { позволит Car иметь ExpandoMetaClass в качестве метакласса. Этот метакласс использует метод invokeMethod, который вы указываете как открытый блок (как и вы), для перехвата вызовов. Это сильно отличается от определения invokeMethod в самом классе.

person blackdrag    schedule 15.06.2015
comment
Не могли бы вы подробнее объяснить, как ExpandoMetaClass меняет стандартный Groovy MOP? @blackdrag - person Samuel Gong; 15.06.2015
comment
Лучше задать конкретный вопрос и потом на него ответить. В целом EMC (ExpandoMetaClass) ведет себя почти так же, как обычный метакласс (MetaClassImpl), но позволяет добавлять методы и свойства, чего нет в стандартном. Одно отличие состоит в том, что измененный EMC (например, вы добавили метод) больше нельзя удалить автоматически. Что касается того, почему именно этот синтаксис был выбран для перехвата звонков... Я не могу на это ответить. Это то, что вы должны спросить, например, у Грэма Роше. - person blackdrag; 16.06.2015
comment
Большое спасибо, @blackdrag - person Samuel Gong; 17.06.2015