Groovy - 为单个实例重写invokeMethod

5
我有一个Java对象的实例,比如一个ArrayList的实例,称为myList。
针对这个特定的实例,我想要覆盖invokeMethod方法以记录该方法被调用的情况。
我可以像下面这样做:
myList.metaclass.invokeMethod { name, args -> 

   println "Called ${name} with ${args}"
   whatGoesHere.invokeMethod(name, args)

}

注意闭包的第二行 - 我如何调用原始的invokeMethod方法?我的做法正确吗?


类似这个答案:在Groovy中找出方法的名称 - Arturo Herrero
Arturo,不幸的是,这个答案适用于整个类,而不是单个实例。 - Roy Truelove
жҲ‘们еҸҜд»ҘдҪҝз”ЁExpandoMetaClassеұһжҖ§д»ҘзӣёеҗҢзҡ„ж–№ејҸеҗ‘е®һдҫӢжҲ–зұ»ж·»еҠ ж–°иЎҢдёәгҖӮ - Arturo Herrero
1个回答

6

可能有一种更短的方法来实现原始方法,但以下方法应该有效:

def myList = [ 1, 2, 3 ]

myList.metaClass.invokeMethod { name, args -> 
   println "Called ${name} with ${args}"
   delegate.class.metaClass.getMetaMethod( name, args )?.invoke( delegate, args )
}

myList.sum()

我发现在 varargs 函数的情况下,当方法被传递一个 ArrayList 时,这种方法会失败。args 将是类型为 Object[] 的数组,其中包含 ArrayList 作为一个元素... 因此它与 getMetaMethod 成功匹配。我认为问题在于它无法将 ArrayList 强制转换为 Object[],因此它会出现“IllegalArgumentException: argument type mismatch”的错误。在我的情况下,解决方法是将一些类型从 ArrayList 切换到 Object[],然后它就可以正常工作了。找出正确的 invokeMethod 修复方法可能需要一些工作。 - brunobowden
处理可变参数的更详细答案:https://dev59.com/44zda4cB1Zd3GeqPnH6L#31143363 - brunobowden
有没有一种方法可以真正调用原始的invokeMethod函数?如果某些其他代码已经修改了元类中的invokeMethod以执行某些操作,如果您使用上述技术,您将覆盖它们的invokeMethod。 - burns

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接