科特林';何时';语句vs Java';开关';
Kotlin中的模式匹配很好,而且在90%的用例中,它不会执行下一个模式匹配 在安卓系统中,当数据库更新时,如果我们不中断代码,我们将使用Java switch属性继续下一种情况:科特林';何时';语句vs Java';开关';,java,switch-statement,kotlin,Java,Switch Statement,Kotlin,Kotlin中的模式匹配很好,而且在90%的用例中,它不会执行下一个模式匹配 在安卓系统中,当数据库更新时,如果我们不中断代码,我们将使用Java switch属性继续下一种情况: switch (oldVersion) { case 1: upgradeFromV1(); case 2: upgradeFromV2(); case 3: upgradeFromV3(); } 因此,如果某人有一个DB版本为1的应用程序,但错过了DB v2的应用程序版本,他将执行所有需
switch (oldVersion) {
case 1: upgradeFromV1();
case 2: upgradeFromV2();
case 3: upgradeFromV3();
}
因此,如果某人有一个DB版本为1的应用程序,但错过了DB v2的应用程序版本,他将执行所有需要的升级代码
转换成Kotlin后,我们会陷入混乱,比如:
when (oldVersion) {
1 -> {
upgradeFromV1()
upgradeFromV2()
upgradeFromV3()
}
2 -> {
upgradeFromV2()
upgradeFromV3()
}
3 -> {
upgradeFromV3()
}
}
这里我们只有3个版本,想象一下当DB达到版本19时
不管怎样,当以同样的方式行事时,是否要进行切换?我试图继续,但没有运气。简单但冗长的解决方案是:
if (oldVersion <= 1) upgradeFromV1()
if (oldVersion <= 2) upgradeFromV2()
if (oldVersion <= 3) upgradeFromV3()
这个怎么样:
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()
}
}
增加:
我喜欢将升级路径定义为列表的想法。这允许为不同的初始阶段定义不同的升级路径。例如:
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) }
}
fun Pair.apply(升级:()->单元):(V)->V{
返回{current:V->
如果(第一个==当前){
升级()
第二
}否则{
现在的
}
}
}
val upgradePath=listOf(
(0到10)。应用{/*做某事*/},
(5到15)应用{/*做某事*/},
(10到20)应用{/*做某事*/},
(15到20)。应用{/*做某事*/},
(20到30)应用{/*做某事*/},
应用{/*做某事*/}
)
趣味升级(旧版:Int){
var当前=旧版本
upgradePath.forEach{current=it(current)}
}
在此代码中,Vs可以与V相同,或者是V值的某种集合,使用重写的
equals(其他:Any?):Boolean
方法。编辑:下面的原始响应。以下是我目前正在做的事情:
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)
}
以下是@C.a.B.给出的答案的一个变体:
fun upgrade(oldVersion: Int) {
when (oldVersion) {
latestVersion -> return
1 -> upgradeFromV1()
2 -> upgradeFromV2()
3 -> upgradeFromV3()
}
upgrade(oldVersion + 1)
}
下面是bashor的两个答案的混合,并添加了一点功能糖:
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() }
}
fun upgradeFromV0(){}
乐趣从v1()升级{}
乐趣从v2()升级到{}
从v3()升级的乐趣{}
val upgrades=arrayOf(::upgradeFromV0,::upgradeFromV1,::upgradeFromV2,::upgradeFromV3)
乐趣升级自(旧版本:Int){
upgrades.filterIndexed{index,kFunction0->oldVersion这是绝对可能的
引用官方参考资料:
因此,如果相同的条件列表很短,那么您可以将它们按彗差分开列出,或者使用类似于1..10中条件的范围,如其他答案中所述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)
}
Kotlin使用另一个称为when的流控制
你的代码,使用它的时候,可以这样
显然,代码可能会有所不同,但我知道您的问题只是关于开关的使用
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);
}
fun main(args:Array){
val月=8
val monthString=时间(月){
1->“里约热内卢”
2->“二月”
3->“三月”
4->“四月”
5->“五月”
6->“六月”
7->“7月”
8->“八月”
9->“9月”
12->“10月”
11->“11月”
10->“12月”
else->“无效月份”
}
println(monthString);
}
对于自定义实现的Kotlin DSL呢?类似于这种方法:
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
}
它打印:
案例1
案例2
案例4
UPD:一些重构和输出示例。您可以在when中使用for循环
for (version in oldVersion..newVersion) when (version) {
1 -> upgradeFromV1()
2 -> upgradeFromV2()
3 -> upgradeFromV3()
}
如果您不关心运行这些函数的顺序,您可以创建自己的伪开关,例如:
function PretendSwitch() {
if(oldVersion>3) return
upgradeFromV3();
if(oldVersion==3) return
upgradeFromV2()
if(oldVersion==2) return
upgradeFromV1()
if(oldVersion==1) return
}
没有什么比使用switch更干净了。不幸的是,Kotlin缺少switch语句,因此无法优雅地执行此操作。val oldVersion=6
val newVersion=10
for (version in oldVersion until newVersion) {
when (version) {
1 -> upgradeFromV1()
2 -> upgradeFromV2()
3 -> upgradeFromV3()
4 -> upgradeFromV4()
5 -> upgradeFromV5()
6 -> upgradeFromV6()
7 -> upgradeFromV7()
8 -> upgradeFromV8()
9 -> upgradeFromV9()
}
println("~~~")
}
我认为统计上(没有证据,但我确信Kotlin团队使用了统计数据)Java中的开关
几乎总是在每种情况下都有一个中断
,因此对于普通情况来说是不方便的函数,你是黄金!@Jerzyna在我当前的解决方案中编辑,在我看来,这稍微好一点。这对OP的问题有什么帮助?谢谢你的回答。虽然它没有直接回答这个问题,但它确实回答了一个以同样方式处理各种情况的相关问题。很好的答案,但你可以使用递归而不是CALI来自的ng方法loop@SurajVaishnav为什么使用递归更好?使用tailrec
会很好,但我认为循环非常简单。这并没有回答最初的问题。这就像无限递归一样loop@C.A.B.我最初的回答暗示,oldVersion
必须在whe中递增n
语句。我编辑了答案,以明确显示必须增加oldVersion
,以避免无限递归。感谢您指出。Kotlin不允许您使用oldVersion++,因为val无法重新分配。您可以改为onUpgrade(db,oldVersion+1,newVersion)@西田,是的,谢谢你的评论。我稍后会删除这篇文章,因为在我看来它和朱利安·德尔菲基的文章没有什么不同。
for (version in oldVersion..newVersion) when (version) {
1 -> upgradeFromV1()
2 -> upgradeFromV2()
3 -> upgradeFromV3()
}
function PretendSwitch() {
if(oldVersion>3) return
upgradeFromV3();
if(oldVersion==3) return
upgradeFromV2()
if(oldVersion==2) return
upgradeFromV1()
if(oldVersion==1) return
}
for (version in oldVersion until newVersion) {
when (version) {
1 -> upgradeFromV1()
2 -> upgradeFromV2()
3 -> upgradeFromV3()
4 -> upgradeFromV4()
5 -> upgradeFromV5()
6 -> upgradeFromV6()
7 -> upgradeFromV7()
8 -> upgradeFromV8()
9 -> upgradeFromV9()
}
println("~~~")
}