我们必须用 Kotlin 中的所有控制流表达式覆盖所有分支?
We have to cover all branches with all Control-Flow expressions in Kotlin?
我从 Kotlin 网站上看了 the docs,只有两个控制流表达式:if
和 when
。
对于if
:
the expression is required to have an else
branch
对于when
:
The else
branch is evaluated if none of the other branch conditions are satisfied. If when
is used as an expression, the else
branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions.
问题
所以好像没有办法不覆盖所有分支的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())
}
}
}
So it seems that there is no way to make a Control-Flow expression
without covering all branches, Is it right?
是
第二种情况
mListener.get()?.loggedOn(LoggedOnUserInfo.IT)
context!!.unregisterReceiver(this)
不再是表达式,整个 if
块是一个语句。
但是,如果您确实需要表达式,您也可以在第一种情况下提供 else
和 Unit
:
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
但最好避免使用此代码,因为它的可读性较差。
这里的技巧是不要使用 if
作为表达式。我的猜测是您将 if
放在 let
块中,returns 它的最后一个语句,因此使用 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
作为表达式。
P.S.
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())
}
}
我从 Kotlin 网站上看了 the docs,只有两个控制流表达式:if
和 when
。
对于if
:
the expression is required to have an
else
branch
对于when
:
The
else
branch is evaluated if none of the other branch conditions are satisfied. Ifwhen
is used as an expression, theelse
branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions.
问题
所以好像没有办法不覆盖所有分支的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())
}
}
}
So it seems that there is no way to make a Control-Flow expression without covering all branches, Is it right?
是
第二种情况
mListener.get()?.loggedOn(LoggedOnUserInfo.IT)
context!!.unregisterReceiver(this)
不再是表达式,整个 if
块是一个语句。
但是,如果您确实需要表达式,您也可以在第一种情况下提供 else
和 Unit
:
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
但最好避免使用此代码,因为它的可读性较差。
这里的技巧是不要使用 if
作为表达式。我的猜测是您将 if
放在 let
块中,returns 它的最后一个语句,因此使用 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
作为表达式。
P.S.
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())
}
}