2011-02-03 5 views
5

Jeśli dodaję meta metody do klasy, spodziewam się, że pojawi się w Class.metaClass.metaMethods. Ale wydaje się, że tak nie jest. W szczególności, jeśli mogę to zrobić:Jaka jest różnica między metaClass.methods a 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" 

ja spodziewałbym wyjście reals = [realFoo], metas = [metaFoo], ale rzeczywiście dostać reals = [realFoo, metaFoo], metas = [].

Wygląda na to, że nowe meta metody są przechowywane metodami, a nie metaMethods. Jaka jest różnica między metaClass.methods i metaClass.metaMethods?

Odpowiedz

6

MetaMethods zawiera te metody, które są dekorowane na klasie przez Groovy, ale w rzeczywistości nie są bezpośrednią częścią struktury klasy lub jej dziedziczenia, lub zostały ręcznie wstawione do klasy przez metaClass.

Są one zdefiniowane w klasie DefaultGroovyMethods.

zależności od rodzaju obiektu jesteś instancji, to głównie iteratory jak każdy, zbierać, znaleźć, itp

Ta modyfikacja kodu pokazuje metody, które są tylko meta, „prawdziwy” tylko i shared:

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 
""" 

Wynik:

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] 

Cała metaOnly i wspólnych metod są w DefaultGroovyMethods. Wszystkie "prawdziwe" metody znajdują się na samej klasie lub na jej klasie nadrzędnej (Object w tym przypadku) plus kilka ciekawych rzeczy bezpośrednio związanych z metaClass, aby uzyskać/ustawić metaClass, jak również getProperty/setProperty i invokeMethod które pozwalają na zastąpienie zachowania metody.

Jeśli chcesz przeszukać wszystkie metody, aby zobaczyć, co istnieje, używam coś takiego:

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