замена toString с помощью метапрограммирования Groovy - PullRequest
12 голосов
/ 19 мая 2010

В следующем фрагменте Groovy я пытаюсь заменить оба метода hashCode и toString

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

Но когда я тестирую, работает только замена hashCode

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

Является ли toString каким-то особым случаем (возможно, по соображениям безопасности)?

Ответы [ 2 ]

5 голосов
/ 19 мая 2010

См. Первый комментарий к этому вопросу . Это говорит о toString String и других связанных с String классах:

(...) похоже на намерение, это, вероятно, хорошая идея иметь более быстрый вызов для классов, которые не позволяют переопределение toString ().

1 голос
/ 05 июня 2014

Это известный дефект . В основном Groovy неправильно корректирует методы, являющиеся частью реализации интерфейса.

Это работает:

class T {
       def doIt() { true }
}

def t = new T()

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

Это не:

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

Поскольку toString() в String происходит от CharSequence, правильный способ переопределения будет:

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