我们必须用 Kotlin 中的所有控制流表达式覆盖所有分支吗?

Jac*_*ong 6 control-flow kotlin

我查看Kotlin 网站上的文档,只有两个控制流表达式:ifwhen.

对于if

表达式需要有一个else分支

对于when

else,如果没有其他满足分支条件分支评估。如果when用作表达式,则else分支是强制性的,除非编译器可以证明所有可能的情况都包含分支条件。

所以好像没有办法在不覆盖所有分支的情况下做一个Control-Flow表达式,是不是?如果没有,有什么办法可以让Control-Flow表达式漏掉一些分支;如果是这样,为什么?


会出现以下代码 if must have both main and 'else' branches if used as an expression

override fun onReceive(context: Context?, intent: Intent?) {
    intent?.let {
        if (it.action == MySDK.BROADCAST_ACTION_LOGIN) {
            mListener.get()?.loggedOn(LoggedOnUserInfo.IT)
        }else if (it.action == MySDK.BROADCAST_ACTION_LOGOUT) {
            // Occur 'if must have both main and 'else' branches if used as an expression'
            mListener.get()?.loggedOut(LoggedOutUserInfo())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是下面的代码通过编译.....

override fun onReceive(context: Context?, intent: Intent?) {
    intent?.let {
        if (it.action == MySDK.BROADCAST_ACTION_LOGIN) {
            mListener.get()?.loggedOn(LoggedOnUserInfo.IT)
            context!!.unregisterReceiver(this) // only add this line to test.
        }else if (it.action == MySDK.BROADCAST_ACTION_LOGOUT) {
            mListener.get()?.loggedOut(LoggedOutUserInfo())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

vod*_*dan 11

这里的技巧不是将 theif用作表达式。我的猜测是您将ifat放置在一个let块中,该块返回其最后一条语句,从而使用 的“结果” if,从而将其视为表达式。

我建议扔掉这个let函数(这里无论如何都没用):

override fun onReceive(context: Context?, intent: Intent?) {
    if(intent != null) {
        if (intent.action == MySDK.BROADCAST_ACTION_LOGIN) {
            mListener.get()?.loggedOn(LoggedOnUserInfo.IT)
        } else if (intent.action == MySDK.BROADCAST_ACTION_LOGOUT) {
            mListener.get()?.loggedOut(LoggedOutUserInfo())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您的第二个版本会编译,因为context!!.unregisterReceiver(this)它的类型与 不同mListener.get()?.loggedOut(LoggedOutUserInfo()),这使得类型不匹配并阻止将if用作表达式。

聚苯乙烯

Kotlin 有不少强大的控制结构。我个人更喜欢这个版本:

override fun onReceive(context: Context?, intent: Intent?) {
    intent ?: return
    when(intent.action) {
        MySDK.BROADCAST_ACTION_LOGIN -> mListener.get()?.loggedOn(LoggedOnUserInfo.IT)
        MySDK.BROADCAST_ACTION_LOGOUT -> mListener.get()?.loggedOut(LoggedOutUserInfo())
    }
}
Run Code Online (Sandbox Code Playgroud)