2010-05-19 8 views
12

Im folgenden Groovy-Schnipsel, versuche ich, die hashCode und toString Methoden zu ersetzen beideersetzt toString mit Groovy metaprogramming

String.metaClass.toString = {-> "override" } 
String.metaClass.hashCode = {-> 22 } 

Aber wenn ich es testen, nur der Ersatz von hashCode arbeitet

String s = "foo" 
println s.hashCode() // prints 22 
println s.toString() // prints "foo" 

Ist toString irgendwie ein Sonderfall (möglicherweise aus Sicherheitsgründen)?

Antwort

5

Siehe den ersten Kommentar on this issue. Er sagt über String toString und andere Klassen String bezogen werden:

(...) scheint Absicht zu sein, es ist wahrscheinlich eine gute Idee, einen schnelleren Aufruf für Klassen zu haben, die nicht zwingenden toString erlauben().

+0

Wie Sie tun wissen, welche "Klassen, die toString() nicht überschreiben"? –

+0

Ich habe eine neue Ausgabe gepostet, die hoffentlich die Dinge klären sollte ... http://jira.codehaus.org/browse/GROOVY-4210 –

+0

Danke Tim, also denke ich, die kurze Antwort ist "es ist ein Fehler"? –

1

Dies ist ein know defect. Groovy überschreibt grundsätzlich nicht die Methoden, die Teil einer Schnittstellenimplementierung sind.

Dies funktioniert:

class T { 
     def doIt() { true } 
} 

def t = new T() 

assert t.doIt() 
t.metaClass.doIt = { -> false } 
assert !t.doIt() 

Dies gilt nicht:

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

Da toString() in String von CharSequence kommt der richtige Weg wäre, außer Kraft zu setzen:

CharSequence.metaClass.toString = {-> "silly"} 
println "hello world".toString()