groovy中的运行时委托
我试图为我自己的项目找出一些东西,所以我举了这个例子来更好地解释它。类groovy中的运行时委托,groovy,Groovy,我试图为我自己的项目找出一些东西,所以我举了这个例子来更好地解释它。类Thing有一个名为overrides的委托Type。在以下情况下,应调用重写中的方法: 该方法在覆盖中声明 该方法在覆盖中声明,但不在` this'中声明 当出现以下情况时,应调用中的方法: 该方法未在覆盖中声明 该方法继承自对象,GroovyObject 缺少方法(缺少方法) 我考虑过使用@Delegate,但我需要在运行时更改覆盖。这是代码 class Thing implements GroovyInterce
Thing
有一个名为overrides
的委托Type
。在以下情况下,应调用重写中的方法:
- 该方法在
覆盖中声明
- 该方法在
覆盖中声明,但不在` this'中声明
当出现以下情况时,应调用中的方法:
- 该方法未在
覆盖中声明
- 该方法继承自
对象
,GroovyObject
- 缺少方法(缺少方法)
我考虑过使用@Delegate,但我需要在运行时更改覆盖。这是代码
class Thing implements GroovyInterceptable {
Type overrides = new BigThing()
Object invokeMethod(String name, Object args) {
MetaMethod thingMethod = metaClass.getMetaMethod('findDeclaredMethod', [this, name, args] as Object[])
.invoke(this, name, args)
MetaMethod overrideMethod = findDeclaredMethod(overrides, name, args)
if(overrideMethod) {
overrideMethod.invoke(overrides, args)
//maybe invoke missingMethod on overrides catch MissingMethodException and call thingMethod
} else if(thingMethod) {
thingMethod.invoke(this, args)
} else {
this.metaClass.invokeMissingMethod(this, name, args)
}
}
MetaMethod findDeclaredMethod(Object obj, String name, Object args) {
MetaMethod m = this.metaClass.getMetaMethod(name, args)
if(m && m.declaringClass.theClass != Thing.getClass()) {
m = null
}
return m
}
String method1() {
return "from Thing method1() ${makeString()}"
}
String method2() {
return "from Thing method2() ${makeString()}"
}
}
interface Type {
String makeString()
}
class BigThing implements Type {
String makeString() {
return "makeString()"
}
String method2() {
return "from BigThing method2() ${makeString()}"
}
}
assert 'from Thing method1() makeString()' == new Thing().method1()
assert 'from BigThing method2() makeString()' == new Thing().method2()
new Thing().with {
assert 'from Thing method1() makeString()' == method1()
assert 'from BigThing method2() makeString()' == method2()
}
注意:这目前不起作用,但我认为它足以解释这个想法
groovy中是否已经有这样的模式
更新:
有了这一点,我已经走了一段路。在使用
闭包的中调用method2()
时失败
class Thing implements GroovyInterceptable {
Type overrides = new BigThing()
Object invokeMethod(String name, Object args) {
MetaMethod method = overrides.metaClass.getMetaMethod(name, args)
if(method != null) {
System.out.println("$method.name class is $method.declaringClass.theClass")
System.out.println("$method.declaringClass.theClass interfaces contains Type or is type ${method.declaringClass.theClass == Type || method.declaringClass.theClass.interfaces.contains(Type)}")
}
if (method != null && (method.declaringClass.theClass == Type || method.declaringClass.theClass.interfaces.contains(Type))) {
return method.invoke(overrides, args)
}
method = this.metaClass.getMetaMethod(name, args)
if (method != null) {
return method.invoke(this, args)
}
return this.metaClass.invokeMissingMethod(this, name, args)
}
String method1() {
return "from Thing method1() ${makeString()}"
}
String method2() {
return "from Thing method2() ${makeString()}"
}
}
interface Type {
String makeString()
}
class BigThing implements Type {
String makeString() {
return "makeString()"
}
String method2() {
return "from BigThing method2() ${makeString()}"
}
}
assert 'from Thing method1() makeString()' == new Thing().method1()
assert 'from BigThing method2() makeString()' == new Thing().method2()
new Thing().with {
assert 'from Thing method1() makeString()' == method1()
assert 'from BigThing method2() makeString()' == method2()
}
尝试简化方法实现。您可以通过以下方式实现该方法:
- 首先检查
覆盖
是否有具有该名称的方法,如果确实存在,则调用该方法
- 检查当前对象是否有具有该名称的方法并调用它
- 调用
invokeMissingMethod
否则
我已经检查了以下实施,并且效果良好:
class Thing implements GroovyInterceptable {
Type overrides = new BigThing()
Object invokeMethod(String name, Object args) {
MetaMethod method = overrides.metaClass.getMetaMethod(name, args)
if (method != null) {
return method.invoke(overrides, args)
}
method = this.metaClass.getMetaMethod(name, args)
if (method != null) {
return method.invoke(this, args)
}
return this.metaClass.invokeMissingMethod(this, name, args)
}
String method1() {
return "from Thing method1() ${makeString()}"
}
String method2() {
return "from Thing method2() ${makeString()}"
}
}
interface Type {
String makeString()
}
class BigThing implements Type {
String makeString() {
return "makeString()"
}
String method2() {
return "from BigThing method2() ${makeString()}"
}
}
assert 'from Thing method1() makeString()' == new Thing().method1()
assert 'from BigThing method2() makeString()' == new Thing().method2()
希望能有帮助。谢谢你的帮助。我到家后得试试。我担心的一件事是GroovyObject方法。我经常使用.with{}
。这些方法中的任何一种都应使用此
。我认为检查声明类将有助于防止在覆盖
@JohnMercier上调用这些方法。您能给我们一个使用.with{}
闭包的示例吗?我也想测试一下:)我已经更新了这个问题,包括一个例子和更多信息。