我想重新实现一个Java类的方法。例如,让"hi".length()返回4。(如何)我能做到吗?我知道使用SomeClass.metaClass我可以获得对现有方法的引用并定义新的(或覆盖)方法,但我似乎不能对现有的Java方法做到这一点。
"hi".length()
4
jchrr9hc1#
使用Groovy,你可以用你自己的实现替换任何方法(甚至final类的方法)。Groovy中的方法替换使用元对象协议,而不是继承。下面是您请求的示例,即如何使String.length()始终返回4
String.length()
// Redefine the method String.metaClass.invokeMethod = { name, args -> def metaMethod = delegate.metaClass.getMetaMethod(name, args) def result = metaMethod.invoke(delegate, args) name == 'length' ? 4 : result } // Test it assert "i_do_not_have_4_chars".length() == 4
krugob8w2#
看起来像是可以通过abusing String metaClass来实现的。但是到目前为止我在groovy控制台中所做的尝试并没有产生预期的结果:
def oldLength = String.metaClass.length String.metaClass.length = { -> return oldLength+10; } println "hi".length()
输出SAD 2我想你可以看看Proxy MetaClass或Delegating metaClass。
2
z9zf31ra3#
如果你重新定义了它,它只能在Groovy代码中工作,Groovy不能改变Java代码的执行方式。在Groovy中,"hi".length()大致相当于下面的Java:
stringMetaClass.invokeMethod("hi","length");
因为Groovy实际上并不直接调用length,所以MetaClass技巧在Groovy代码中是有效的,但是Java不知道MetaClass,所以没有办法让它工作。
hfsqlsce4#
虽然这个问题已经很老了,但我还是想指出另一种方式(至少对于较新的Groovy版本来说是这样)。java.lang.String中的length()方法是从java.lang.CharSequence接口实现的。为了使用String-metaClass重新实现该方法,您需要首先“覆盖”接口的metaClass中的方法。
java.lang.String
length()
java.lang.CharSequence
CharSequence.metaClass.length = { -> -1} String.metaClass.length = { -> 4 } assert "i_do_not_have_4_chars".length() == 4
使用String.metaClass.invokeMethod的解决方案改变了所有String方法的行为,存在问题。例如,简单地调用"asdf".size()会导致我的设置出现异常。
String.metaClass.invokeMethod
"asdf".size()
4条答案
按热度按时间jchrr9hc1#
使用Groovy,你可以用你自己的实现替换任何方法(甚至final类的方法)。Groovy中的方法替换使用元对象协议,而不是继承。
下面是您请求的示例,即如何使
String.length()
始终返回4krugob8w2#
看起来像是可以通过abusing String metaClass来实现的。但是到目前为止我在groovy控制台中所做的尝试并没有产生预期的结果:
输出SAD
2
我想你可以看看Proxy MetaClass或Delegating metaClass。
z9zf31ra3#
如果你重新定义了它,它只能在Groovy代码中工作,Groovy不能改变Java代码的执行方式。
在Groovy中,
"hi".length()
大致相当于下面的Java:因为Groovy实际上并不直接调用length,所以MetaClass技巧在Groovy代码中是有效的,但是Java不知道MetaClass,所以没有办法让它工作。
hfsqlsce4#
虽然这个问题已经很老了,但我还是想指出另一种方式(至少对于较新的Groovy版本来说是这样)。
java.lang.String
中的length()
方法是从java.lang.CharSequence
接口实现的。为了使用String-metaClass重新实现该方法,您需要首先“覆盖”接口的metaClass中的方法。使用
String.metaClass.invokeMethod
的解决方案改变了所有String方法的行为,存在问题。例如,简单地调用"asdf".size()
会导致我的设置出现异常。