with - Instrução "When" vs Java "switch"




with kotlin example (7)

É absolutamente possível citar a partir da referência oficial: Fluxo de Controle: se, quando, por, enquanto

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

Portanto, se a mesma lista de condições for curta, você poderá listá-las separando por coma ou usar intervalos como condição em 1..10, conforme indicado em outras respostas

https://code.i-harness.com

A correspondência de padrões no Kotlin é agradável e o fato de não executar a próxima correspondência de padrões é boa em 90% dos casos de uso.

No Android, quando o banco de dados é atualizado, usamos a propriedade Java switch para continuar no próximo caso, se não interrompermos o código da seguinte maneira:

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

Portanto, se alguém tiver um aplicativo com a versão 1 do banco de dados e tiver perdido a versão do aplicativo com o DB v2, ele executará todo o código de atualização necessário.

Convertido para Kotlin, temos uma bagunça como:

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

Aqui temos apenas 3 versões, imagine quando o DB atingir a versão 19: /

Enfim, faz quando age da mesma maneira que mudar? Eu tentei continuar sem sorte.


A solução simples mas prolixo é:

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

Outra solução possível com referências de função :

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

E o DSL Kotlin para implementação personalizada? Algo como esta abordagem:

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
}

Imprime: case 1 case 2 case 4 UPD: Algumas refatorações e exemplo de saída.


Kotlin trabalha com um controle de fluxo diferente chamado when.

Seu código, quando usado, pode ser assim.

Obviamente, o código pode ser diferente, mas entendo que sua pergunta é apenas sobre o uso do 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);
}

Que tal agora:

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

Adicionado:

Gosto da idéia do @lukle de definir o caminho da atualização como uma lista. Isso permite definir diferentes caminhos de atualização para diferentes estágios iniciais. Por exemplo:

  1. Caminho rápido simples da versão lançada para a versão mais recente
  2. Caminho de recuperação da versão de hotfix (pode ser pequena em uma linha), que não deve ser aplicada ao passar da versão completa anterior para a próxima versão completa

Para isso, precisamos saber de quais elementos da lista aplicar.

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

Nesse código, Vs pode ser o mesmo que V ou algum tipo de coleção de valores de V com equals(other: Any?): Boolean substituídos equals(other: Any?): Boolean Método equals(other: Any?): Boolean .


Você pode usar for loop com when.

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

val orders = arrayListOf(
            { upgradeFromV1()},
            { upgradeFromV2()},
            { upgradeFromV3()}
)

orders.drop(oldVersion).forEach { it() }




kotlin