2017-09-26 49 views
1

我想弄清楚自己的项目,所以我让这个例子更好地解释它。类Thing有一个代表Type调用overrides。当overrides方法应该叫:groovy中的运行时代表团

  • 方法在overrides
  • 方法在overrides宣布已宣告但尚未在`在this这个

方法应该叫时:

  • 该方法未在overrides
  • 中声明
  • 该方法是从Object继承,GroovyObject
  • 方法缺失(missingMethod)

我一直在使用@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()with关闭中失败。

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() 
} 

回答

0

尝试简化GroovyObject.invokeMethod(String name, Object args)方法的实现。您可以通过实施该方法在下列方式实现这一目标:

  • 首先检查是否overrides有方法使用该名称,并调用它,如果它确实存在
  • 检查,如果当前的对象有方法使用该名称,并调用它
  • 调用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() 

我希望它有帮助。

+0

感谢您的帮助。当我回家时,我将不得不尝试它。我担心的一件事是GroovyObject方法。我使用'.with {}'很多。任何这些方法都应该使用'this'。我认为声明类的检查将有助于防止在'overrides'上调用这些方法。 –

+0

@JohnMercier您能否给我们一个使用'.with {}'关闭的例子?我也想测试它:) –

+0

我已经更新了问题,以包括一个例子和更多的信息。 –