Kotlin 'when' statement vs Java 'switch'

2022-09-02 14:13:28

Kotlin 中的模式匹配很不错,在 90% 的用例中,它不执行下一个模式匹配的事实很好。

在 Android 中,当数据库更新时,如果我们不中断以使代码如下所示,我们将使用 Java switch 属性继续下一个案例:

switch (oldVersion) {
    case 1: upgradeFromV1();
    case 2: upgradeFromV2(); 
    case 3: upgradeFromV3();
}

因此,如果有人的应用程序具有 DB 版本 1,并且错过了 DB v2 的应用程序版本,他将执行所有必需的升级代码。

转换为 Kotlin 后,我们会得到如下混乱:

when (oldVersion) {
    1 -> {
        upgradeFromV1()
        upgradeFromV2()
        upgradeFromV3()
    }
    2 -> {
        upgradeFromV2()
        upgradeFromV3()
    }
    3 -> {
        upgradeFromV3()
    }
}

这里我们只有3个版本,想象一下当DB达到版本19时。

无论如何,当以同样的方式行事时,那么切换?我试图在没有运气的情况下继续前进。


答案 1

简单但冗长的解决方案是:

if (oldVersion <= 1) upgradeFromV1()
if (oldVersion <= 2) upgradeFromV2()
if (oldVersion <= 3) upgradeFromV3()

另一个可能的解决方案与函数参考

fun upgradeFromV0() {}
fun upgradeFromV1() {}
fun upgradeFromV2() {}
fun upgradeFromV3() {}

val upgrades = arrayOf(::upgradeFromV0, ::upgradeFromV1, ::upgradeFromV2, ::upgradeFromV3)

fun upgradeFrom(oldVersion: Int) {
    for (i in oldVersion..upgrades.lastIndex) {
        upgrades[i]()
    }
}

答案 2

编辑:原始响应如下。以下是我目前正在做的事情:

fun upgrade() {
    fun upgradeFromV1() { /* Do stuff */ }
    fun upgradeFromV3() { /* Do stuff */ }

    tailrec fun upgradeFrom(version: Int): Unit = when (version) {
        LATEST_VERSION -> {
            Config.version = version
        } 1 -> {
            upgradeFromV1()
            upgradeFrom(2)
        } in 2..3 -> {
            upgradeFromV3()
            upgradeFrom(4)
        } else -> {
            Log("Uncaught upgrade from $version")
            upgradeFrom(version+1)
    }

    upgradeFrom(Config.version)
}

以下是@C.A.B.给出的答案的变体:

fun upgrade(oldVersion: Int) {
    when (oldVersion) {
        latestVersion -> return
        1 -> upgradeFromV1()
        2 -> upgradeFromV2()
        3 -> upgradeFromV3()
    }
    upgrade(oldVersion + 1)
}