首先申明下,本文为笔者学习《Groovy 程序设计》的笔记,并加入笔者自己的理解和归纳总结。
1. 动态访问
访问属性
class AGroovyClass {
int value = 10
}
obj = new AGroovyClass()
pName = "value"
println obj["value"] // 10
println obj.value // 10
println obj["$pName"] // 10
println obj."$pName" // 10
obj.properties.each {
println it
}
// value=10
// class=class AGroovyClass
println obj.properties.value // 10
访问方法
class AGroovyClass {
def add(val1, val2) {
val1 + val2
}
}
obj = new AGroovyClass()
mName = 'add'
method = AGroovyClass.metaClass.getMetaMethod(mName, null, null)
println method.invoke(obj, 11, 13) // 24
println method.invoke(obj, "Hello ", "World!") // Hello World!
println obj.invokeMethod(mName, [11, 13]) // 24
println obj.invokeMethod(mName, ["Hello ", "World!"]) // Hello World!
2. Expando类提供了动态合成类的能力。
动态属性
peopleA = new Expando()
peopleA.name = "Jack"
peopleA["addr"] = "ShangHai"
println peopleA // {name=Jack, addr=ShangHai}
peopleB = new Expando(name : "Mike", addr : "ShengZhen")
println peopleB // {name=Mike, addr=ShengZhen}
动态方法
peopleA = new Expando(name : "Jack", addr : "ShangHai", toString : { "$name live in $addr" } )
println peopleA.toString() // Jack live in ShangHai
peopleB = new Expando(name : "Mike", addr : "ShengZhen")
peopleB.toString = { "$name live in $addr" }
println peopleB.toString() // Mike live in ShengZhen
3. 方法合成
方法合成在调用时动态地确定方法的行为。
在GroovyObject
中合成方法,使用methodMissing()
方法来拦截未定义方法并进行处理。
class AGroovyClass {
def methodMissing(String name, args) {
println "In methodMissing " + name
if (name == "add") {
println "In add function"
}
}
}
obj = new AGroovyClass()
obj.add()
obj.del()
obj.add()
返回
In methodMissing add
In add function
In methodMissing del
In methodMissing add
In add function
把动态办法添加到metaClass
中,这样不必每次都进入methodMissing()
方法中。缓存add()
方法,第二次调用时直接使用metaClass
中add()
方法,提高了效率。
class AGroovyClass {
def methodMissing(String name, args) {
println "In methodMissing " + name
if (name == "add") {
println "In add function"
def func = { Object[] vargs ->
println "in add func " + vargs
}
AGroovyClass instance = this
instance.metaClass."$name" = func
func(args)
}
}
}
obj = new AGroovyClass()
obj.add(11)
obj.add(11, 12)
obj.add("Hello ", "World!")
返回
In methodMissing add
In add function
in add func [11]
in add func [11, 12]
in add func [Hello , World!]
在GroovyInterceptable
中合成方法,使用invokeMethod()
方法来拦截未定义方法并进行处理。每次都先查询metaClass中
是否存在该方法,存在的话直接调用,不存在的再定义。
class AnInterceptable implements GroovyInterceptable {
def invokeMethod(String name, args) {
System.out.println("In invokeMethod " + name)
def method = metaClass.getMetaMethod(name, args)
if (method) { // 直接进行方法调用
method.invoke(this, args)
} else { // 调用metaClass的invokeMethod方法,会在methodMissing中重新定义。
metaClass.invokeMethod(this, name, args)
}
}
def methodMissing(String name, args) {
System.out.println("In methodMissing " + name)
if (name == "add") {
System.out.println("In add function");
def func = { Object[] vargs ->
System.out.println("in add func " + vargs)
}
AnInterceptable instance = this
instance.metaClass."$name" = func
func(args)
}
}
}
obj = new AnInterceptable()
obj.add(11)
obj.add(11, 12)
obj.add("Hello ", "World!")
返回
In invokeMethod add
In methodMissing add
In add function
in add func [11]
In invokeMethod add
in add func [11, 12]
In invokeMethod add
in add func [Hello , World!]
MetaClass
合成
class AGroovyClass {
}
AGroovyClass.metaClass.methodMissing = { String name, args ->
println "In methodMissing " + name
if (name == "add") {
println "In add function"
def func = { Object[] vargs ->
println "in add func " + vargs
}
AGroovyClass.metaClass."$name" = func
func(args)
}
}
obj = new AGroovyClass()
obj.add(11)
obj.add(11, 12)
obj.add("Hello ", "World!")
返回
In methodMissing add
In add function
in add func [11]
in add func [11, 12]
in add func [Hello , World!]
4. 动态委托
将Teacher
的工作委托给各个科目去完成。
class Chinese {
def chineseTech() {
println "Chinese Teacher do the work"
}
}
class English {
def englishTech() {
println "Chinese Teacher do the work"
}
}
class Math {
def mathTech() {
println "Chinese Teacher do the work"
}
}
class Teacher {
Teacher() {
delegateTo Chinese, English, Math
}
def delegateTo(Class... classes) {
def objOfDelegate = classes.collect { it.newInstance() }
Teacher instance = this
instance.metaClass.methodMissing = { String name, args ->
println "In methodMissing"
def delegate = objOfDelegate.find {
it.metaClass.respondsTo(it, name, args)
}
if (delegate) {
instance.metaClass."$name" = { Object[] vargs ->
delegate.invokeMethod(name, vargs)
}
delegate.invokeMethod(name, args)
} else {
println "no delegate"
}
}
}
}
tech = new Teacher();
tech.chineseTech()
tech.englishTech()
tech.mathTech()
tech.mathTech()
tech.physicsTech()
返回
In methodMissing
Chinese Teacher do the work
In methodMissing
English Teacher do the work
In methodMissing
Math Teacher do the work
Math Teacher do the work
In methodMissing
no delegate