Kotlin 'when' statement vs Java 'switch'

前端 未结 10 1036
感情败类
感情败类 2020-12-03 06:41

Pattern matching in Kotlin is nice and the fact it does not execute the next pattern match is good in 90% of use cases.

In Android, when database is updated, we use J

相关标签:
10条回答
  • 2020-12-03 06:49

    You can just use for loop with when.

    for (version in oldVersion..newVersion) when (version) {
        1 -> upgradeFromV1()
        2 -> upgradeFromV2()
        3 -> upgradeFromV3()
    }
    
    0 讨论(0)
  • 2020-12-03 06:49

    Here is a mix of the two answers from bashor, with a little bit of functional sugar:

    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() }
    }
    
    0 讨论(0)
  • 2020-12-03 06:52

    How about this:

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

    Added:

    I like the idea by @lukle to define the upgrade path as a list. This allows to define different upgrade paths for different initial stage. For example:

    1. Simple fast path from released version to the latest released version
    2. Catch-up path from hot-fix version (could be few in a row), which should not be applied when going from previous full version to the next full version

    For that we need to know from which elements of the list to apply.

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

    In this code Vs could be the same as V or some kind of collection of V values with overridden equals(other: Any?): Boolean method.

    0 讨论(0)
  • 2020-12-03 06:56

    It is absolutly possible quote from official reference : Control Flow: if, when, for, while

    If many cases should be handled in the same way, the branch conditions may be combined with a comma:
    
    when (x) {
        0, 1 -> print("x == 0 or x == 1")
        else -> print("otherwise")
    }
    

    So if same condition list is short, then you can list them separating by coma, or use ranges like condition in 1..10 as stated in other answers

    0 讨论(0)
  • 2020-12-03 06:59

    What about Kotlin DSL for custom implementation? Something like this approach:

    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
    }
    

    It prints: case 1 case 2 case 4 UPD: Some refactorings and output example.

    0 讨论(0)
  • 2020-12-03 06:59

    Kotlin works with a different flow control called when.

    Your code, using it when, can be that way.

    Obviously the code could be different, but I understand that your question is only about the use of switch.

    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);
    }
    
    0 讨论(0)
提交回复
热议问题