Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 case (possibly for security reasons)?

like image 541
Dónal Avatar asked May 19 '10 10:05

Dónal


2 Answers

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().

like image 195
Felipe Cypriano Avatar answered Sep 28 '22 02:09

Felipe Cypriano


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()
like image 39
Kshitiz Sharma Avatar answered Sep 28 '22 04:09

Kshitiz Sharma