是否可以在 Kotlin 的 while 条件体中初始化变量?

Is it possible to init a variable in the while condition body for Kotlin?

在下面的代码中:

    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(我们是在这些行上没有相应的错误)。

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

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

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

var verticesCount: Int

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

    ...
}

val resultGraph = Graph(verticesCount)

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

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

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

任何表达式都可以是 "extended" 和 "something to do",方法是调用 also,将调用它的表达式作为 it 参数并执行给定的块。值 also returns 与其调用者值相同。

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