Заменяя toString с помощью метапрограммирования Groovy
В следующем фрагменте 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
каким-то особым случаем (возможно, из соображений безопасности)?
Ответы
Ответ 1
См. первый комментарий по этой проблеме. Он говорит о String toString и других связанных с String классах:
(...) кажется намеренным, это, вероятно, хорошая идея иметь более быстрый вызов для классов, которые не позволяют переопределение toString().
Ответ 2
Это знать дефект.
В принципе 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()