为什么类对象上的方法闭包失败



在 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 中是否有阻止其工作等的东西?

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

MethodClosure 中的doCall方法覆盖 Closure 的doCall,并使用 invokeMethod 而不是从 Closure 调用call()来截获方法调用。

如果您明确使用MethodClosuredoCall的同义词InvokerHelper或只是metaClass列表,则该MethodClosure也将起作用。

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 上创建的。

最新更新