你应该已经知道,groovy是一种动态编程语言,使得我们可以在运行时期将任何方法添加到任何类。为了更好的理解 MetaClass。 从一个简单的元编程(MetaProgramming)示例开始,其中我们在Integer类中添加了一个方法(isEvent)。
// 一个无参方法.
Integer.metaClass.isEven = { ->
delegate%2 == 0
}
可以思考一下,上面的 metaClass 是什么?deletegate 代理的是谁?元编程如何工作?怎样关闭元编程能力?inEven() 是静态方法还是实例方法?isEven() 是添加给特定对象吗?怎样给对象添加多个方法?如果知道或许你也不会打开这片文章😂😂,下面就来一一讲述:
什么是metaClass
在Groovy语言中,每个对象都有一个名称为metaClass的MetaClass类的对象。 此metaClass对象负责保存与该对象有关的所有信息。 每当您对该对象执行任何操作时,Groovy的调度机制都会通过该元类对象(metaClass)路由调用。 因此,如果要更改任何对象/类的行为,则必须更改附加到该类/对象的MetaClass对象,并且它将在运行时更改该类/对象的行为。
deletegate 代理的是谁
大白话来说,谁调用就代理谁(实例对象)。
元编程(MetaProgramming)如何工作
每个 Groovy 对象都有一个名为metaClass的MetaClass类的对象,所以当我们调用方法时,都会到 metaClass 保存的信息中查找。如果找到就会调用,比如上面的方法,可以这么用。
Integer.metaClass.isEven = { ->
delegate%2 == 0
}
int a = 10
int b = 11
println "a.isEven(): ${a.isEven()}"
println "b.isEven(): ${b.isEven()}"
输出结果如下:
a.isEven(): true
b.isEven(): false
这个也好理解嘛!对 2 求余数,偶数为0,奇数为1。
怎样关闭元编程能力
这个就相当简单了, 把 metaClass 置空就搞定了。
Integer.metaClass = null
// 这样就找不到方法定义了 No signature of method: java.lang.Integer.isEven() is applicable for argument types: () values: []
a.isEven()
inEven() 是静态方法还是实例方法
inEven() 是实例方法,如果要定义静态方法,需要像下面这样:
Integer.metaClass.static.isEven = { number ->
number%2 == 0
}
// 如果是静态方法,参数肯定就只能传进去了,而不能再通过实例调用啦!
Integer.isEven(1) // false
Integer.isEven(2) // true
isEven() 是添加给特定对象吗
isEven() 是添加到所有的 Interger 对象。如果只想给特定的对象添加,需要像下面这样:
Integer aNumber = 9
aNumber.metaClass.isEven = { ->
delegate%2 == 0
}
println aNumber.isEven() // false
println 2.isEven() // will throw MissingMethodException.
怎样给对象添加多个方法
需要添加多个方法,可以像下面这样:
Integer.metaClass {
isEven { -> delegate%2 == 0 }
isOdd { -> delegate%2 != 0 }
// other methods
}
println 6.isEven() // true
println 6.isOdd() // false