Der Musterabgleich in Kotlin ist nett und die Tatsache, dass der nächste Musterabgleich nicht ausgeführt wird, ist in 90 % der Anwendungsfälle gut.
Wenn die Datenbank in Android aktualisiert wird, verwenden wir die Java-Switch-Eigenschaft, um mit dem nächsten Fall fortzufahren, wenn wir keine Pause machen, damit der Code so aussieht:
switch (oldVersion) {
case 1: upgradeFromV1();
case 2: upgradeFromV2();
case 3: upgradeFromV3();
}
Wenn also jemand eine App mit Version 1 der DB hat und die App-Version mit DB v2 verpasst hat, wird er den gesamten erforderlichen Upgrade-Code ausführen lassen.
In Kotlin konvertiert, erhalten wir ein Durcheinander wie:
Ich denke statistisch (keine Beweise, aber ich bin sicher, dass das Kotlin-Team Statistiken verwendet hat, um zu entscheiden), dass a switch in Java hat fast immer a break in jedem Fall, daher ist es für den allgemeinen Fall unbequem.
– Jayson Minard
5. Januar 2016 um 22:08 Uhr
Bashor
Einfache, aber wortreiche Lösung ist:
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]()
}
}
Tolle Antwort, aber Sie können Rekursion verwenden, anstatt die Methode aus der for-Schleife aufzurufen
– Suraj Vaishnav
29. Dezember 2017 um 16:46 Uhr
@SurajVaishnav Warum ist die Rekursion besser? Verwenden tailrec wäre in Ordnung, aber die Schleife ist ziemlich einfach, IMO.
– EM
19. März 2020 um 22:30 Uhr
Julian Delphiki
edit: Ursprüngliche Antwort unten. Folgendes mache ich gerade:
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)
}
Füge hinzu ein Schwanzrez Modifikator für die (rekursiv aufgerufene) Funktion und Sie sind goldrichtig!
– Jerzyna
15. März 2017 um 10:17 Uhr
@Jerzyna in meiner aktuellen Lösung bearbeitet, die meiner Meinung nach etwas schöner ist.
– Julian Delphiki
20. April 2017 um 17:12 Uhr
TAXI
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()
}
}
Hinzugefügt:
Ich mag die Idee von @lukle, den Upgrade-Pfad als Liste zu definieren. Dies ermöglicht es, verschiedene Upgrade-Pfade für verschiedene Anfangsstufen zu definieren. Zum Beispiel:
Einfacher schneller Weg von der veröffentlichten Version zur neuesten veröffentlichten Version
Aufholpfad von der Hotfix-Version (könnte mehrere hintereinander sein), der nicht angewendet werden sollte, wenn von der vorherigen Vollversion zur nächsten Vollversion gewechselt wird
Dazu müssen wir wissen, ab welchen Elementen der Liste wir uns bewerben.
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 diesem Code könnte Vs dasselbe sein wie V oder eine Art Sammlung von V-Werten mit Überschreibung equals(other: Any?): Boolean Methode.
Sie können einfach die for-Schleife mit when verwenden.
for (version in oldVersion..newVersion) when (version) {
1 -> upgradeFromV1()
2 -> upgradeFromV2()
3 -> upgradeFromV3()
}
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")
}
Wenn also dieselbe Bedingungsliste kurz ist, können Sie sie durch Komma trennen oder Bereiche wie Bedingung in 1..10 verwenden, wie in anderen Antworten angegeben
Wie hilft das bei OPs Problem?
– Melpomen
24. Juni 2017 um 21:29 Uhr
Danke für diese Antwort. Obwohl es die Frage nicht direkt beantwortet, beantwortet es eine verwandte Frage zur Behandlung verschiedener Fälle auf die gleiche Weise
– Das es
20. Juli 2017 um 2:05 Uhr
Eine andere Variante der Antwort von 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)
}
Wie hilft das bei OPs Problem?
– Melpomen
24. Juni 2017 um 21:29 Uhr
Danke für diese Antwort. Obwohl es die Frage nicht direkt beantwortet, beantwortet es eine verwandte Frage zur Behandlung verschiedener Fälle auf die gleiche Weise
– Das es
20. Juli 2017 um 2:05 Uhr
Was ist mit Kotlin DSL für die benutzerdefinierte Implementierung? Etwa dieser Ansatz:
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
}
Es druckt:
case 1
case 2
case 4
UPD: Einige Refactorings und Ausgabebeispiele.
11586500cookie-checkKotlin ‘when’-Anweisung vs. Java ‘switch’yes
Gerade gestolpert youtrack.jetbrains.com/issue/KT-771 dann irgendein Workaround?
– Geob-o-matic
14. Juni 2015 um 17:12 Uhr
Ich denke statistisch (keine Beweise, aber ich bin sicher, dass das Kotlin-Team Statistiken verwendet hat, um zu entscheiden), dass a
switch
in Java hat fast immer abreak
in jedem Fall, daher ist es für den allgemeinen Fall unbequem.– Jayson Minard
5. Januar 2016 um 22:08 Uhr