Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
科特林';何时';语句vs Java';开关';_Java_Switch Statement_Kotlin - Fatal编程技术网

科特林';何时';语句vs Java';开关';

科特林';何时';语句vs Java';开关';,java,switch-statement,kotlin,Java,Switch Statement,Kotlin,Kotlin中的模式匹配很好,而且在90%的用例中,它不会执行下一个模式匹配 在安卓系统中,当数据库更新时,如果我们不中断代码,我们将使用Java switch属性继续下一种情况: switch (oldVersion) { case 1: upgradeFromV1(); case 2: upgradeFromV2(); case 3: upgradeFromV3(); } 因此,如果某人有一个DB版本为1的应用程序,但错过了DB v2的应用程序版本,他将执行所有需

Kotlin中的模式匹配很好,而且在90%的用例中,它不会执行下一个模式匹配

在安卓系统中,当数据库更新时,如果我们不中断代码,我们将使用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时


不管怎样,当以同样的方式行事时,是否要进行切换?我试图继续,但没有运气。

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

if (oldVersion <= 1) upgradeFromV1()
if (oldVersion <= 2) upgradeFromV2()
if (oldVersion <= 3) upgradeFromV3()
这个怎么样:

fun upgradeFromV3() {/* some code */}
fun upgradeFromV2() {/* some code */ upgradeFromV3()}
fun upgradeFromV1() {/* some code */ upgradeFromV2()}
fun upgradeFromV0() {/* some code */ upgradeFromV1()}

fun upgrade(oldVersion: Int) {
    when (oldVersion) {
        1 -> upgradeFromV1()
        2 -> upgradeFromV2()
        3 -> upgradeFromV3()
    }
}
增加:

我喜欢将升级路径定义为列表的想法。这允许为不同的初始阶段定义不同的升级路径。例如:

  • 从发布版本到最新发布版本的简单快速路径
  • 从热修复程序版本(可能是一行中的少数版本)的追赶路径,在从上一个完整版本转到下一个完整版本时不应应用该路径
  • 为此,我们需要知道列表中的哪些元素适用

    fun <Vs, V> Pair<Vs, V>.apply(upgrade: () -> Unit): (V) -> V {
        return { current: V ->
            if (first == current) {
                upgrade()
                second
            } else {
                current
            }
        }
    }
    
    val upgradePath = listOf(
            (0 to 10).apply  { /* do something */ },
            (5 to 15).apply  { /* do something */ },
            (10 to 20).apply { /* do something */ },
            (15 to 20).apply { /* do something */ },
            (20 to 30).apply { /* do something */ },
            (30 to 40).apply { /* do something */ }
    )
    
    fun upgrade(oldVersion: Int) {
        var current = oldVersion
        upgradePath.forEach { current = it(current) }
    }
    
    fun Pair.apply(升级:()->单元):(V)->V{
    返回{current:V->
    如果(第一个==当前){
    升级()
    第二
    }否则{
    现在的
    }
    }
    }
    val upgradePath=listOf(
    (0到10)。应用{/*做某事*/},
    (5到15)应用{/*做某事*/},
    (10到20)应用{/*做某事*/},
    (15到20)。应用{/*做某事*/},
    (20到30)应用{/*做某事*/},
    应用{/*做某事*/}
    )
    趣味升级(旧版:Int){
    var当前=旧版本
    upgradePath.forEach{current=it(current)}
    }
    

    在此代码中,Vs可以与V相同,或者是V值的某种集合,使用重写的
    equals(其他:Any?):Boolean
    方法。

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

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

    下面是bashor的两个答案的混合,并添加了一点功能糖:

    fun upgradeFromV0() {}
    fun upgradeFromV1() {}
    fun upgradeFromV2() {}
    fun upgradeFromV3() {}
    
    val upgrades = arrayOf(::upgradeFromV0, ::upgradeFromV1, ::upgradeFromV2, ::upgradeFromV3)
    
    fun upgradeFrom(oldVersion: Int) {
        upgrades.filterIndexed { index, kFunction0 -> oldVersion <= index }
                .forEach { it() }
    }
    
    fun upgradeFromV0(){}
    乐趣从v1()升级{}
    乐趣从v2()升级到{}
    从v3()升级的乐趣{}
    val upgrades=arrayOf(::upgradeFromV0,::upgradeFromV1,::upgradeFromV2,::upgradeFromV3)
    乐趣升级自(旧版本:Int){
    upgrades.filterIndexed{index,kFunction0->oldVersion这是绝对可能的
    引用官方参考资料:


    因此,如果相同的条件列表很短,那么您可以将它们按彗差分开列出,或者使用类似于1..10中条件的范围,如其他答案中所述

    OP答案的另一个变体:

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        when (oldVersion) {
            newVersion -> return
            1 -> TODO("upgrade from v1 to v2")
            2 -> TODO("upgrade from v2 to v3")
        }
        oldVersion++
        onUpgrade(db, oldVersion, newVersion)
    }
    

    Kotlin使用另一个称为when的流控制

    你的代码,使用它的时候,可以这样

    显然,代码可能会有所不同,但我知道您的问题只是关于开关的使用

    fun main(args: Array<String>) {
    val month = 8
    
    val monthString = when(month) {
        1 -> "Janeiro"
        2 -> "February"
        3 -> "March"
        4 -> "April"
        5 -> "May"
        6 -> "June"
        7 -> "July"
        8 -> "August"
        9 -> "September"
        12 -> "October"
        11 -> "November"
        10 -> "December"
        else -> "Invalid month"      
    }
    
    println(monthString);
    }
    
    fun main(args:Array){
    val月=8
    val monthString=时间(月){
    1->“里约热内卢”
    2->“二月”
    3->“三月”
    4->“四月”
    5->“五月”
    6->“六月”
    7->“7月”
    8->“八月”
    9->“9月”
    12->“10月”
    11->“11月”
    10->“12月”
    else->“无效月份”
    }
    println(monthString);
    }
    
    对于自定义实现的Kotlin DSL呢?类似于这种方法:

    class SwitchTest {
    
        @Test
        fun switchTest() {
    
            switch {
                case(true) {
                    println("case 1")
                }
                case(true) {
                    println("case 2")
                }
                case(false) {
                    println("case 3")
                }
                caseBreak(true) {
                    println("case 4")
                }
                case(true) {
                    println("case 5")
                }
    //          default { //TODO implement
    //
    //          }
            }
        }
    }
    
    class Switch {
        private var wasBroken: Boolean = false
    
        fun case(condition: Boolean = false, block: () -> Unit) {
            if (wasBroken) return
            if (condition)
                block()
        }
    
        fun caseBreak(condition: Boolean = false, block: () -> Unit) {
            if (condition) {
                block()
                wasBroken = true
            }
        }
    }
    
    fun switch(block: Switch.() -> Unit): Switch {
        val switch = Switch()
        switch.block()
        return switch
    }
    
    它打印:
    
    案例1
    案例2
    案例4
    

    UPD:一些重构和输出示例。

    您可以在when中使用for循环

    for (version in oldVersion..newVersion) when (version) {
        1 -> upgradeFromV1()
        2 -> upgradeFromV2()
        3 -> upgradeFromV3()
    }
    

    如果您不关心运行这些函数的顺序,您可以创建自己的伪开关,例如:

    function PretendSwitch() {
      if(oldVersion>3) return
      upgradeFromV3();
      if(oldVersion==3) return
      upgradeFromV2()
      if(oldVersion==2) return
      upgradeFromV1()
      if(oldVersion==1) return
    }
    
    没有什么比使用switch更干净了。不幸的是,Kotlin缺少switch语句,因此无法优雅地执行此操作。

    val oldVersion=6 val newVersion=10

    for (version in oldVersion until newVersion) {
        when (version) {
            1 -> upgradeFromV1()
            2 -> upgradeFromV2()
            3 -> upgradeFromV3()
            4 -> upgradeFromV4()
            5 -> upgradeFromV5()
            6 -> upgradeFromV6()
            7 -> upgradeFromV7()
            8 -> upgradeFromV8()
            9 -> upgradeFromV9()
        }
        println("~~~")
    }
    

    我认为统计上(没有证据,但我确信Kotlin团队使用了统计数据)Java中的
    开关
    几乎总是在每种情况下都有一个
    中断
    ,因此对于普通情况来说是不方便的函数,你是黄金!@Jerzyna在我当前的解决方案中编辑,在我看来,这稍微好一点。这对OP的问题有什么帮助?谢谢你的回答。虽然它没有直接回答这个问题,但它确实回答了一个以同样方式处理各种情况的相关问题。很好的答案,但你可以使用递归而不是CALI来自的ng方法loop@SurajVaishnav为什么使用递归更好?使用
    tailrec
    会很好,但我认为循环非常简单。这并没有回答最初的问题。这就像无限递归一样loop@C.A.B.我最初的回答暗示,
    oldVersion
    必须在
    whe中递增n
    语句。我编辑了答案,以明确显示必须增加
    oldVersion
    ,以避免无限递归。感谢您指出。Kotlin不允许您使用oldVersion++,因为val无法重新分配。您可以改为onUpgrade(db,oldVersion+1,newVersion)@西田,是的,谢谢你的评论。我稍后会删除这篇文章,因为在我看来它和朱利安·德尔菲基的文章没有什么不同。
    for (version in oldVersion..newVersion) when (version) {
        1 -> upgradeFromV1()
        2 -> upgradeFromV2()
        3 -> upgradeFromV3()
    }
    
    function PretendSwitch() {
      if(oldVersion>3) return
      upgradeFromV3();
      if(oldVersion==3) return
      upgradeFromV2()
      if(oldVersion==2) return
      upgradeFromV1()
      if(oldVersion==1) return
    }
    
    for (version in oldVersion until newVersion) {
        when (version) {
            1 -> upgradeFromV1()
            2 -> upgradeFromV2()
            3 -> upgradeFromV3()
            4 -> upgradeFromV4()
            5 -> upgradeFromV5()
            6 -> upgradeFromV6()
            7 -> upgradeFromV7()
            8 -> upgradeFromV8()
            9 -> upgradeFromV9()
        }
        println("~~~")
    }