我们必须用Kotlin中的所有Control-Flow表达式覆盖所有分支?

我查看了 Kotlin网站上的文档 ,只有两个Control-Flow表达式: ifwhen

if

该表达式需要有一个else分支

对于when

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

所以似乎没有办法在没有覆盖所有分支的情况下创建一个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()) } } } 

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

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

这里的诀窍是不使用if作为表达式。 我的猜测是,你把if放在一个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()) } } } 

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

PS

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

所以似乎没有办法在没有覆盖所有分支的情况下创建一个Control-Flow表达式,是不是?

在第二种情况下

 mListener.get()?.loggedOn(LoggedOnUserInfo.IT) context!!.unregisterReceiver(this) 

不是一个表达了,整个if块是一个声明。 但是,如果您确实需要表达式,则还可以在第一种情况下为Unit提供else

 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()) } else Unit 

但是最好避免这个代码,因为它的可读性较差。