2015-06-14 4 views
34

di corrispondenza nella Kotlin è bello e il fatto che non esegue la prossima partita modello è buona nel 90% dei casi d'uso."Quando" dichiarazione vs Java "switch" dichiarazione

In Android, quando il database viene aggiornato, usiamo Java passare proprietà per andare in caso successivo se non mettiamo una pausa per avere il codice alla ricerca di simile:

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

Quindi, se qualcuno ha un app con versione 1 del DB e ha perso la versione dell'app con DB v2, otterrà tutto il codice di aggiornamento necessario eseguito.

Convertito in Kotlin, otteniamo un pasticcio come:

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

Qui abbiamo solo 3 versione, immaginate quando DB raggiunge la versione 19:/

Comunque per marche quando agisce nella stessa maniera di quanto interruttore? Ho provato a continuare senza fortuna.

+0

Proprio imbattuti in https://youtrack.jetbrains.com/issue/KT-771 qualsiasi soluzione allora? –

+1

Penso statisticamente (nessuna prova, ma sono sicuro squadra Kotlin utilizzato le statistiche per decidere) che un 'switch' in Java ha quasi sempre un' break' in ogni caso, quindi è scomodo per il caso comune. –

risposta

50

Soluzione semplice ma prolisso è:

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

Un'altra possibile soluzione con 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

Grande risposta, ma è possibile utilizzare la ricorsione invece di metodo da chiamare per il ciclo –

10

ne dite di questo:

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

edit: risposta originale al di sotto. Ecco quello che sto facendo attualmente:

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

Ecco una variazione della risposta @ C.A.B. dato:

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

Aggiungi un modificatore [tailrec] (https://kotlinlang.org/docs/reference/functions.html#tail-recursive-functions) al (ricorsivamente chiamato) e tu sei d'oro! – Jerzyna

+0

@Jerzyna modificato nella mia attuale soluzione, che è leggermente più bella, secondo me. –

0

qui è un mix delle due risposte da Bashor, con un po 'di zucchero funzionale:

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

E' assolutamente possibile citazione da riferimento offisial 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") 
} 

quindi se stessa lista condizione è breve, allora è possibile elencare separandole da coma oppure usa gli intervalli come condizione in 1..10 come detto in altre risposte

+0

In che modo questo aiuta con il problema di OP? – melpomene

+0

Grazie per questa risposta. Sebbene non risponda direttamente alla domanda, risponde a una domanda correlata relativa alla gestione di vari casi nello stesso modo – TheIT

+0

Questa risposta mi ha aiutato :), grazie. – moxi

0

Un'altra variazione della risposta di 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() }