如果我将meta方法添加到类中,我希望它会显示在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.methods
和metaClass.metaMethods
有什么区别? 最佳答案
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和共享方法都在DefaultGroovyMethods中。所有“真实”方法都在类本身或其父类上(在本例中为Object),再加上一些与metaClass直接相关的常规事物,以获取/设置metaClass以及getProperty/setProperty和invokeMethod它允许您覆盖方法行为。
如果您想搜索所有方法以查看存在的方法,请使用类似以下内容的方法:
def allMethods = (Example.metaClass.methods + Example.metaClass.metaMethods).name.sort().unique()