3

在下面的代码中:

    var verticesCount: Int // to read a vertices count for graph

    // Reading until we get a valid vertices count.
    while (!Assertions.checkEnoughVertices(
            verticesCount = consoleReader.readInt(null, Localization.getLocStr("type_int_vertices_count"))))
        // The case when we don't have enough vertices.
        println(String.format(Localization.getLocStr("no_enough_vertices_in_graph"),
                              Assertions.CONFIG_MIN_VERTICES_COUNT))

    val resultGraph = Graph(verticesCount)

我们在最后一行收到下一个错误:

Error:(31, 33) Kotlin: Variable 'verticesCount' must be initialized

Assertions.checkEnoughVertices接受一个安全类型变量作为参数 (verticesCount: Int),因此 verticesCount 不可能在此处未初始化或为 null(我们在这些行上没有得到相应的错误)。

当已经初始化的变量再次变为未初始化时,最后一行发生了什么?

4

2 回答 2

6

您使用的语法表示带有命名参数的函数调用,而不是局部变量的赋值。所以verticesCount =只是向读者解释,这里传递的值checkEnoughVertices对应于名为 的函数的参数verticesCount。它与上面声明的局部变量无关verticesCount,因此编译器认为您仍然需要初始化该变量。

在 Kotlin 中,对变量 ( a = b)的赋值不是表达式,因此不能在其他表达式中用作值。您必须拆分分配和 while 循环条件才能实现您想要的。我会用无限循环+里面的条件来做到这一点:

var verticesCount: Int

while (true) {
    verticesCount = consoleReader.readInt(...)
    if (Assertions.checkEnoughVertices(verticesCount)) break

    ...
}

val resultGraph = Graph(verticesCount)
于 2016-07-07T21:30:18.327 回答
3

好吧,从技术上讲,可以在 while 条件下为变量赋值 - 以及您可能想要在那里做的任何其他事情。魔力来自also函数:

试试这个:(原谅这是完全没用的事情......)

var i = 10
var doubleI: Int
while ((i * 2).also { doubleI = it } > 0) {
    i--
    println(doubleI)
}

also任何表达式都可以通过调用将被调用的表达式作为it参数并执行给定的块来“扩展”为“要做的事情” 。返回的值also与其调用者值相同。

这是一篇非常好的文章来解释这一点以及更多内容:https ://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84

于 2018-12-07T20:32:50.643 回答