metaClass.methods和metaClass.metaMethods有什么区别?

时间:2011-02-03 18:28:48

标签: groovy metaprogramming

如果我向类中添加元方法,我希望它会显示在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 = []

看起来新的元方法存储在方法中,而不是metaMethods。那么,metaClass.methodsmetaClass.metaMethods之间的区别是什么?

1 个答案:

答案 0 :(得分:6)

MetaMethods包含由Groovy在类上修饰的那些方法,但实际上并不是类的直接部分或它的继承结构,或者是通过metaClass手动插入类的。

这些是在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和shared方法都在DefaultGroovyMethods中。所有“真正的”方法都在类本身上,或者在它的父类(在本例中为Object)上,加上一些与metaClass直接相关的groovy事物来获取/设置metaClass以及getProperty / setProperty和invokeMethod它允许您覆盖方法行为。

如果您想搜索所有方法以查看存在的内容,我会使用以下内容:

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