Kotlin中toString的递归问题
我用Kotlin写XML DSL,遇到了一个问题。 码:
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) }
我该如何解决这个问题?
当你从joinToString
函数的lambda参数调用toString
,你没有指定toString
的接收者。 在这种情况下,使用范围内的隐式接收器。 这指向父元素,而不是当前的孩子,所以你正在进行递归调用。
在那个lambda里面,你应该访问具有隐式参数名称的子元素,或者明确地命名参数。
children.joinToString("\n") { it.toString() } children.joinToString("\n") { child -> child.toString() }
但是,这不会使递归类型检查问题消失,因为这里同样的toString
被引用在它的内部,其类型尚未被推断。 要打破这种递归,你需要明确指定toString
的返回类型。
override fun toString(): String = ...
我是Kotlin的新手,所以这可能不是很习惯。 它工作,虽然。
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) }