2011-02-03 8 views
5

Se aggiungo un metodo meta a una classe, mi aspetto che venga visualizzato in Class.metaClass.metaMethods. Ma questo sembra non essere il caso. In particolare, se faccio questo:Qual è la differenza tra metaClass.methods e 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" 

mi aspetto di uscita del reals = [realFoo], metas = [metaFoo], ma io in realtà ottenere reals = [realFoo, metaFoo], metas = [].

Sembra che i nuovi metodi meta siano memorizzati in metodi, non in metametodi. Quindi, qual è la differenza tra metaClass.methods e metaClass.metaMethods?

risposta

6

MetaMethods contiene quei metodi che sono decorati sulla classe da Groovy, ma che non sono in realtà una parte diretta della classe o della sua struttura di ereditarietà o che sono stati inseriti manualmente nella classe attraverso la metaClass.

Questi sono definiti nella classe DefaultGroovyMethods.

A seconda del tipo di oggetto che stai istanziare, è per lo più iteratori come ogni, raccogliere, trovare, ecc

Questa modifica al codice mostra i metodi che sono meta unica, "reale" solo, e in comune:

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

Risultato:

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] 

Tutto il metaonly e metodi condivisi sono in DefaultGroovyMethods. Tutti i metodi "reali" si trovano sulla classe stessa o sulla sua classe genitore (oggetto in questo caso), oltre a un paio di cose groovy direttamente correlate alla metaClass per ottenere/impostare la metaClass e getProperty/setProperty e invokeMethod che ti consentono di sovrascrivere il comportamento del metodo.

Se vuoi per la ricerca in tutti i metodi per vedere ciò che esiste, io uso qualcosa di simile:

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