Рекурсивная проблема с toString в Котлине

Я пишу XML DSL с Kotlin и столкнулся с проблемой. Код:

abstract class Element(val name: String) { var children = mutableListOf<Element>() override fun toString() = """ <$name> ${children.joinToString("\n") { toString() }} </$name> """.trimIndent() } 

У меня есть следующая ошибка в { toString() } :

Проверка типов прошла рекурсивную задачу. Самое простое обходное решение: явно указать типы ваших объявлений.

Мне нужен следующий вывод:

 <a> <b> </b> <c> </c> </a> 

Если у меня есть следующий код:

 fun main(args: Array<String>) { val a = Element("a") a.children.add(Element("b")) a.children.add(Element("c")) println(a) } 

Как я могу решить эту проблему?

Когда вы вызывали toString из аргумента joinToString функции joinToString , вы не указали получателя этого toString . В этом случае используется неявный приемник в области. Это указывает на родительский элемент, а не на текущий ребенок, поэтому вы делаете рекурсивный вызов.

Внутри этого лямбда вам нужно получить доступ к дочернему элементу с имплицитным именем параметра или указать его явно.

 children.joinToString("\n") { it.toString() } children.joinToString("\n") { child -> child.toString() } 

Однако это не приведет к тому, что проблема проверки рекурсивного типа исчезнет, ​​потому что здесь тот же самый указатель toString внутри его тела, тип которого еще предстоит вывести. Чтобы разбить эту рекурсию, вам нужно явно указать тип возвращаемого значения toString .

 override fun toString(): String = ... 

Я полный новичок с Котлином, поэтому это не может быть очень идиоматичным. Это работает.

 class Element(val name: String) { var children = mutableListOf<Element>() private fun recursiveToString(depth: Int): String { fun tabulations(amount: Int) = "\t".repeat(amount) val childrenAsString: String = children.joinToString("") { tabulations(depth + 1) + it.recursiveToString(depth + 1) } return "<$name>\n$childrenAsString${tabulations(depth)}</$name>\n" } override fun toString() = recursiveToString(0) } fun main(args: Array<String>) { val a = Element("a") a.children.add(Element("b")) val c = Element("c") c.children.add(Element("d")) a.children.add(c) println(a) } 
Intereting Posts
Android: отправка данных обратно в MainActivity Как передать только один параметр функции, когда он ожидает два? Android с изменением даты и времени, но снова надавить, Firebase просто возвращает истекший токен Массив вложенных пар в котлин Можно ли сохранить «Unit» в качестве возвращаемого типа функции Kotlin при вызове с Java? Kotlin – Инициализация имущества с использованием «ленивым» и «lateinit» RxJava2 Может быть возвращено пустое Наблюдаемое, если ни один элемент RxJava – Входы клавиатуры с обратным давлением? Недействительный Mutable Map Пустой конструктор для объекта kotlin для использования Firebase Spring Boot + Kotlin AutoProxyRegistrar вызывает исключение Nullpointer Обоснованные дженерики в Scala 2.10 При использовании сопрограмм kotlin, как я могу тестировать функцию, вызывающую функцию приостановки? Kotlin: Сортировка | Расположение операции свопинга Нечеткость разрешения перегрузки Котлина в стандартной библиотеке