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{}
闭包的示例吗?我也想测试一下:)我已经更新了这个问题,包括一个例子和更多信息。