我们必须用Kotlin中的所有Control-Flow表达式覆盖所有分支?
我查看了 Kotlin网站上的文档 ,只有两个Control-Flow表达式: if
和when
。
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
但是最好避免这个代码,因为它的可读性较差。
- Kotlin parcelable类抛出ClassNotFoundException
- Kotlin Custom View类实现了一个无法在`:app:compileDebugKotlinAfterJava`中解析的接口。 相同的Java版本正常工作