В чем разница между metaClass.methods и metaClass.metaMethods? - PullRequest
5 голосов
/ 03 февраля 2011

Если я добавлю мета-метод в класс, я ожидаю, что он появится в Class.metaClass.metaMethods. Но, похоже, это не так. В частности, если я сделаю это:

class Example {
    def realFoo() { "foo" }

}
Example.metaClass.metaFoo = { -> "foo" }

def reals = Example.metaClass.methods*.name.grep{it.contains("Foo")}
def metas = Example.metaClass.metaMethods*.name.grep{it.contains("Foo")}

println "reals = $reals, metas = $metas"

Я бы ожидал вывод reals = [realFoo], metas = [metaFoo], но на самом деле получаю reals = [realFoo, metaFoo], metas = [].

Похоже, новые мета-методы хранятся в методах, а не в мета-методах. Итак, в чем разница между metaClass.methods и metaClass.metaMethods?

1 Ответ

6 голосов
/ 04 февраля 2011

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

Они определены в DefaultGroovyMethods классе.

В зависимости от типа объекта, который вы создаете, это в основном итераторы, такие как каждый, собирать, находить и т. Д.

Эта модификация вашего кода показывает методы, которые являются только мета, "реальными" и общими:

class Example {
    def realFoo() { "foo" }

}
Example.metaClass.metaFoo = { -> "foo" }

def reals = Example.metaClass.methods.name.sort().unique()
def metas = Example.metaClass.metaMethods.name.sort().unique()

def metaOnly = metas - reals
def realOnly = reals - metas
def shared = reals.findAll { metas.contains(it) }

println """
metaOnly = $metaOnly
realOnly = $realOnly
shared = $shared
"""

Результат:

metaOnly = [addShutdownHook, any, asBoolean, asType, collect, dump, each, eachWithIndex, every, find, findAll, findIndexOf, findIndexValues, findLastIndexOf, findResult, getAt, getMetaPropertyValues, getProperties, grep, hasProperty, identity, inject, inspect, is, isCase, iterator, metaClass, print, printf, println, putAt, respondsTo, sleep, split, sprintf, use, with]
realOnly = [equals, getClass, getProperty, hashCode, metaFoo, notify, notifyAll, realFoo, setProperty, wait]
shared = [getMetaClass, invokeMethod, setMetaClass, toString]

Все методы metaOnly и общего доступа находятся в DefaultGroovyMethods. Все «настоящие» методы находятся в самом классе или в его родительском классе (в данном случае в Object), плюс пара отличных вещей, непосредственно связанных с metaClass для получения / установки metaClass, а также getProperty / setProperty и invokeMethod которые позволяют вам переопределить поведение метода.

Если вы хотите просмотреть все методы, чтобы увидеть, что существует, я использую что-то вроде этого:

def allMethods = (Example.metaClass.methods + Example.metaClass.metaMethods).name.sort().unique() 
...