replacing toString using Groovy metaprogramming
In the following Groovy snippet, I attempt to replace both the hashCode
and toString
methods
String.metaClass.toString = {-> "override" }
String.metaClass.hashCode = {-> 22 }
But when I test it out, only the replacement of hashCode
works
String s = "foo"
println s.hashCode() // prints 22
println s.toString() // prints "foo"
Is toString
somehow a special 开发者_Go百科case (possibly for security reasons)?
See the first comment on this issue. It says about String's toString and other String related classes:
(...) seems to be intent, it is probably a good idea to have a faster invocation for classes that don't allow overriding toString().
This is a know defect. Basically Groovy does not correctly override methods that are part of an interface implementation.
This works:
class T {
def doIt() { true }
}
def t = new T()
assert t.doIt()
t.metaClass.doIt = { -> false }
assert !t.doIt()
This doesn't:
interface I {
def doIt()
}
class T implements I {
def doIt() { true }
}
def t = new T()
assert t.doIt()
t.metaClass.doIt = { -> false }
assert !t.doIt()
Because toString()
in String
comes from CharSequence
the correct way to override would be:
CharSequence.metaClass.toString = {-> "silly"}
println "hello world".toString()
精彩评论