2017-08-31 22 views
0

我用Kotlin編寫XML DSL並遇到問題。代碼:Kotlin的toString遞歸問題

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

我怎樣才能解決這個問題?

回答

1

當您從joinToString函數的lambda參數調用toString時,您並未指定該toString的接收方。在這種情況下,使用範圍內的隱式接收器thisthis指向父元素而不是當前子元素,因此您正在進行遞歸調用。

在那個lambda中,您應該訪問帶有隱式參數名稱it的子元素,或者明確地命名參數。

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

然而,這不會使遞歸類型檢查問題消失,因爲這裏同樣toString是其體內引用,其類型尚未推斷。要打破這種遞歸,您需要明確指定返回類型toString

override fun toString(): String = ... 
+0

謝謝!現在我有'StackOverflowError',但我認爲這是另一回事;) – Feeco

1

我是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) 
} 
+0

謝謝,它的工作原理!我建議你閱讀[字符串插值](https://kotlinlang.org/docs/reference/idioms.html#string-interpolation)。 – Feeco