Есть ли kotlin способ ограничения переопределения toString () для класса с делегированными свойствами - PullRequest
0 голосов
/ 21 октября 2019

Я новичок в Kotlin, и я пробовал примеры в документации для пользовательских делегированных свойств.

https://try.kotlinlang.org/#/Examples/Delegated%20properties/Custom%20delegate/Custom%20delegate.kt

обычно при переопределении метода toString, я ограничиваю поля, которые яхотите печатать как в предоставленном коде.

В этом случае, p является delagated свойством, где мы используем thisref в строке getValue (). Поэтому здесь возникает проблема переполнения стека из-за рекурсивных вызовов.

class Example {
    var p: String by Delegate()
    var q: String = "testQ"

    override fun toString() = "Example[p=$p]"
}

class Delegate() {
    operator fun getValue(thisRef: Any?, prop: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${prop.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: String) {
        println("$value has been assigned to ${prop.name} in $thisRef")
    }
}

Поскольку делегированные свойства предназначены для общей библиотеки, есть ли какие-то ограничения на метод переопределения toString (), которому мы должны следовать.

Ответы [ 2 ]

1 голос
/ 21 октября 2019
return "$thisRef ... "

В строке выше вы хотите вызвать thisRef.toString() (в строковых шаблонах неявно вызывается toString). И он пытается выполнить следующую строку: "Example[p=$p]". Итак, он пытается снова вызвать thisRef.toString(), и мы снова находимся в "Example[p=$p]" call.

Было бы сказано, что это абсолютно ожидаемое поведение. Что вы можете сделать тогда? В вашем случае просто удалите вызов thisRef.toString из вашего метода делегата.

1 голос
/ 21 октября 2019

Проблема не в делегате, а в рекурсии:

  1. Example.toString () вызывается
  2. Delegate.getValue () вызывается $p. Экземпляр Example передается в getValue.
  3. Example.toString () вызывается $thisRef. Таким образом, он возвращается к шагу 1 !!

Вы можете воспроизвести то же самое на этом очень простом примере:

fun main() {
    class SimpleExample {
        override fun toString() = "$this"
    }

    println(SimpleExample())
}

Чтобы исправить это, удалите $thisRef изфункция getValue.

...