【问题标题】:Why does a method closure on a Class object fail?为什么 Class 对象的方法闭包会失败?
【发布时间】:2013-07-17 02:12:50
【问题描述】:

在 groovy 中创建方法闭包非常容易,例如:

groovy:000> p = 1.&plus
===> org.codehaus.groovy.runtime.MethodClosure@a7981d5
groovy:000> p(3)
===> 4

但是,由于某种原因,它在尝试使用 Class 的实例时失败:

groovy:000> List.isInstance([])
===> true
groovy:000> t = List.&isInstance
===> org.codehaus.groovy.runtime.MethodClosure@31ca1a68
groovy:000> t([])
ERROR groovy.lang.MissingMethodException:
No signature of method: java.util.List.isInstance() is applicable for argument types: (java.util.ArrayList) values: [[]]
        at groovysh_evaluate.run (groovysh_evaluate:2)
        ...
groovy:000> t = List.class.&isInstance
===> org.codehaus.groovy.runtime.MethodClosure@7b34c5ff
groovy:000> t([])
ERROR groovy.lang.MissingMethodException:
No signature of method: java.util.List.isInstance() is applicable for argument types: (java.util.ArrayList) values: [[]]
        at groovysh_evaluate.run (groovysh_evaluate:2)
        ...

解决这个问题很容易,但我想了解为什么会发生这种情况。 MOP 中有什么东西可以阻止它工作吗?

【问题讨论】:

    标签: groovy closures


    【解决方案1】:

    当您在Class 的实例上使用方法指针时,它必须显式使用MethodClosure 提供的doCall() 方法,而不是使用Closure 的默认call()

    来自MethodClosuredoCall 方法覆盖Closure 的doCall 并通过使用invokeMethod 而不是从Closure 调用call() 来拦截方法调用。

    如果您在MethodClosure 或简单地使用metaClass 列表中明确使用与doCall 同义的InvokerHelperMethodClosure 也将起作用。

    import org.codehaus.groovy.runtime.InvokerHelper
    
    t = List.&isInstance
    
    assert t.owner.simpleName == 'List'
    assert t.doCall([]) == true    
    assert InvokerHelper.getMetaClass(t.owner).
                  invokeStaticMethod(t.owner, 'isInstance', []) == true
    assert List.metaClass.invokeStaticMethod(t.owner, 'isInstance', []) == true
    

    如果对象是Class 的实例,则使用MOP 的invokeStaticMethod

    另一方面,&plus 可以正常工作,因为方法指针是在 POJO 上创建的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-30
      • 1970-01-01
      相关资源
      最近更新 更多