2015-06-14 14 views
34

Mustererkennung in Kotlin ist nett und die Tatsache, dass es nicht nächste Musterübereinstimmung führt, ist gut in 90% der Anwendungsfälle."When" Anweisung vs Java "switch" Anweisung

In Android, wenn Datenbank aktualisiert wird, verwenden wir Java-Eigenschaft einschalten nächsten Fall zu gehen, wenn wir Code wie die Suche nicht eine Pause gesetzt haben:

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

Also, wenn jemand eine App hat mit Version 1 der DB und verpasste die App-Version mit DB v2, er wird alle benötigten Upgrade-Code ausgeführt.

Umgerechnet auf Kotlin, bekommen wir ein Chaos wie:

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

Hier haben wir nur 3-Version haben, vorstellen, wenn DB-Version erreicht 19:/

Auf jeden Fall macht, wenn in gleicher Weise wirkt als Schalter? Ich habe es weiter ohne Glück versucht.

+0

stolperte auf https://youtrack.jetbrains.com/issue/KT-771 jede Abhilfe dann? –

+1

Ich denke statistisch (keine Beweise, aber ich bin mir sicher, dass das Kotlin-Team Statistiken verwendet hat), dass ein 'Switch' in Java fast immer eine 'Pause' hat, daher ist es unbequem für den allgemeinen Fall. –

Antwort

50

Einfach, aber wortreich Lösung ist:

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

Eine andere mögliche Lösung mit function references:

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

Große Antwort, aber Sie können Rekursion anstelle von Aufruf der Methode von For-Schleife verwenden –

10

Wie wäre es damit:

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

bearbeiten: Original Antwort unten. Hier ist, was ich momentan mache:

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

Hier ist eine Variante der Antwort @ C.A.B. gab:

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

Fügen Sie einen [tailrec] (https://kotlinlang.org/docs/reference/functions.html#tail-recursive-functions) Modifikator zum (rekursiv genannt) funktionieren und du bist golden! – Jerzyna

+0

@ Jerzyna in meiner aktuellen Lösung bearbeitet, die meiner Meinung nach etwas schöner ist. –

0

Hier ist eine Mischung aus den beiden Antworten von bashor, mit einem wenig funktionellen Zucker ist:

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

Es Zitat von offisial Referenz https://kotlinlang.org/docs/reference/control-flow.html

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") 
} 
absolutly möglich ist

Wenn also die Liste der gleichen Bedingungen kurz ist, können Sie sie nach Koma auflisten, oder verwenden Sie Bereiche wie Bedingung in 1..10 wie in anderen Antworten angegeben

+0

Wie hilft das mit OP's Problem? – melpomene

+0

Danke für diese Antwort. Obwohl es nicht direkt die Frage beantwortet, beantwortet es eine verwandte Frage der Behandlung verschiedener Fälle in der gleichen Weise – TheIT

+0

Diese Antwort half mir :), danke. – moxi

0

Eine weitere Variante der Antwort des OP:

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { 
    when (oldVersion) { 
     newVersion -> return 
     1 -> TODO("upgrade from v1") 
     2 -> TODO("upgrade from v2") 
    } 
    onUpgrade(db, oldVersion,newVersion) 
} 
-1
val orders = arrayListOf(
      { upgradeFromV1()}, 
      { upgradeFromV2()}, 
      { upgradeFromV3()} 
) 

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