2015-06-14 15 views
34

Kết hợp mẫu trong Kotlin rất đẹp và thực tế nó không thực hiện khớp mẫu tiếp theo là tốt trong 90% trường hợp sử dụng.Câu lệnh "Khi" tuyên bố so với Java "chuyển đổi"

Trong Android, khi cơ sở dữ liệu được cập nhật, chúng tôi sử dụng Java chuyển tài sản để đi về trường hợp tiếp theo nếu chúng ta không đặt một break để có mã tìm kiếm như thế:

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

Vì vậy, nếu ai đó có một ứng dụng với phiên bản 1 của DB và bỏ lỡ phiên bản ứng dụng với DB v2, anh ta sẽ nhận được tất cả mã nâng cấp cần thiết được thực hiện.

Converted để Kotlin, chúng tôi có được một mớ hỗn độn như:

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

Ở đây chúng ta chỉ có 3 phiên bản, hãy tưởng tượng khi DB đạt phiên bản 19:/

Dù sao để làm cho khi diễn xuất trong cùng một cách hơn công tắc điện? Tôi đã cố gắng tiếp tục mà không có may mắn.

+0

Chỉ cần vấp trên https://youtrack.jetbrains.com/issue/KT-771 bất kỳ cách giải quyết sau đó? –

+1

Tôi nghĩ thống kê (không có bằng chứng, nhưng tôi chắc rằng nhóm Kotlin đã sử dụng số liệu thống kê để quyết định) rằng 'chuyển đổi 'trong Java hầu như luôn có' ngắt' trong mỗi trường hợp, do đó nó là bất tiện cho trường hợp thông thường. –

Trả lời

50

Đơn giản nhưng dài dòng giải pháp là:

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

Một giải pháp khả thi với 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

Câu trả lời hay, nhưng bạn có thể sử dụng đệ quy thay vì gọi phương thức từ vòng lặp –

10

Làm thế nào về điều này:

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

chỉnh sửa: phản ứng gốc bên dưới. Đây là những gì tôi đang thực hiện:

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

Dưới đây là một biến thể của câu trả lời @ C.A.B. tặng:

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

Thêm công cụ sửa đổi [tailrec] (https://kotlinlang.org/docs/reference/functions.html#tail-recursive-functions) vào (đệ quy) gọi là) chức năng và bạn vàng! – Jerzyna

+0

@Jerzyna đã chỉnh sửa trong giải pháp hiện tại của tôi, điều này hơi đẹp hơn, theo ý kiến ​​của tôi. –

0

Đây là một kết hợp của hai câu trả lời từ bashor, với một chút đường chức năng:

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

Đó là absolutly thể trích dẫn từ tài liệu tham khảo 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") 
} 

Vì vậy, nếu danh sách điều kiện tương tự ngắn, thì bạn có thể liệt kê chúng tách biệt bằng hôn mê hoặc sử dụng các phạm vi như điều kiện trong 1..10 như được nêu trong các câu trả lời khác

+0

Điều đó giúp gì cho vấn đề của OP? – melpomene

+0

Cảm ơn câu trả lời này. Mặc dù nó không trả lời trực tiếp câu hỏi, nhưng nó trả lời một câu hỏi liên quan đến việc xử lý các trường hợp khác nhau theo cùng một cách – TheIT

+0

Câu trả lời này đã giúp tôi :), cảm ơn. – moxi

0

Một biến thể của câu trả lời OP của:

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() } 
Các vấn đề liên quan