在不详尽的情况下使用 Kotlin 的作用域函数 with / when
Using Kotlin's scope functions in not exhaustive with / when
我是 Kotlin
的新手,我正在尝试了解 Kotlin 的 scope functions
。
我的代码如下所示:
with(something) {
when {
equals("test") -> var1 = "test123"
startsWith("test2") -> var2 = "test456"
contains("test3") -> myNullableVar?.let { it.var3 = "test789" }
}
}
因此,在我使用 .let
函数进行第三次检查之前,我的 with
函数不需要详尽无遗(我不是 returning 某些东西,我只是做作业)。在我的第三次检查中,我使用 .let
作为空检查...但仅用于 it.var3
的分配(如果它不是 null
)。我不需要 return 任何东西,而我知道 Kotlin 的 .let
函数 return 是主体的标准结果。
尽管如此,现在我的 with/when
需要详尽无遗,否则它将无法再编译。
这让我开始思考和尝试不同的事情。我找到了这些方法来解决这个问题:
- 我可以在我的
with/when
中添加一个 else
,这样它就变得详尽无遗,但实际上我不需要 else,我不想在这种情况下使用它。
- 我可以添加另一个
.let
,所以它看起来像这样:myNullableVar?.let { it.var3 = "test789" }.let{}
....但这对我来说有点老套。它应该像这样工作吗?
- 使用
If(xy==null){...}else{...}
东西,但我想我可以用 Kotlin 以不同的方式解决这个问题
因为我是 Kotlin 的新手,所以我不太确定如何正确处理这种情况。我可能会接受我的第二个想法,因为“它有效”。还是我不应该使用 .let
进行空值检查?再加一个空的.let{}
?还是我根本没有理解空安全概念?我觉得这里有点失落。感谢您的帮助。
这似乎是一个不幸的功能组合……
A when
只有当它不是 return 值时才可以是 non-exhaustive。问题是 with()
函数 做 return 一个值。由于 when
在底部,它的值是 returned 的值,所以在这种情况下它必须是详尽无遗的。
那么,为什么它不坚持 else
分支,即使您省略了“test3”分支?那是因为赋值不会产生值。 (它们的计算结果为 Unit
,这是 Kotlin 对没有 return 有用值的函数的特殊类型。)如果每个分支都给出 Unit
,那么 Kotlin 似乎 * 很高兴推断出默认分支也给出了 Unit
.
但是“test3”分支 return 是其他东西 — myNullableVar
的类型。那么 when
推断出什么类型呢?该类型和 Unit
最接近的公共超类型,即顶级类型 Any?
。 现在 它需要一个明确的 else
分支!
那怎么办?
您找到了几个选项,none 其中最理想的。所以这里还有一些,同上!
您可以 return 来自该分支的显式 Unit
:
contains("test3") -> { myNullableVar?.let { it.var3 = "test789" }; Unit }
您可以 return 来自 with()
的显式 Unit
:
contains("test3") -> myNullableVar?.let { it.var3 = "test789" }
}
Unit
}
您可以为 with()
指定一个明确的类型。 (它有 两个 类型参数,因此您需要同时提供这两个参数,从其参数的类型开始):
with<String, Unit>("abc") {
恐怕我还没有找到一个明显的最佳答案……
然后回答你的最后一个问题:是的,?.let{
是完全惯用的,并且对于空值检查很常见。在这种特殊情况下,将其替换为 if
恰好解决了类型问题:
contains("test3") -> { if (myNullableVar != null) myNullableVar.var3 = "test789" }
但是除了 long-winded,如果 myNullableVar
是一个 属性 而不是局部变量,那么它会打开一个竞争条件(如果另一个线程将它设置为null 在测试和赋值之间?)所以编译器会抱怨——这正是人们使用 let
的原因!
(*我找不到此行为的参考资料。有官方说法吗?)
我是 Kotlin
的新手,我正在尝试了解 Kotlin 的 scope functions
。
我的代码如下所示:
with(something) {
when {
equals("test") -> var1 = "test123"
startsWith("test2") -> var2 = "test456"
contains("test3") -> myNullableVar?.let { it.var3 = "test789" }
}
}
因此,在我使用 .let
函数进行第三次检查之前,我的 with
函数不需要详尽无遗(我不是 returning 某些东西,我只是做作业)。在我的第三次检查中,我使用 .let
作为空检查...但仅用于 it.var3
的分配(如果它不是 null
)。我不需要 return 任何东西,而我知道 Kotlin 的 .let
函数 return 是主体的标准结果。
尽管如此,现在我的 with/when
需要详尽无遗,否则它将无法再编译。
这让我开始思考和尝试不同的事情。我找到了这些方法来解决这个问题:
- 我可以在我的
with/when
中添加一个else
,这样它就变得详尽无遗,但实际上我不需要 else,我不想在这种情况下使用它。 - 我可以添加另一个
.let
,所以它看起来像这样:myNullableVar?.let { it.var3 = "test789" }.let{}
....但这对我来说有点老套。它应该像这样工作吗? - 使用
If(xy==null){...}else{...}
东西,但我想我可以用 Kotlin 以不同的方式解决这个问题
因为我是 Kotlin 的新手,所以我不太确定如何正确处理这种情况。我可能会接受我的第二个想法,因为“它有效”。还是我不应该使用 .let
进行空值检查?再加一个空的.let{}
?还是我根本没有理解空安全概念?我觉得这里有点失落。感谢您的帮助。
这似乎是一个不幸的功能组合……
A when
只有当它不是 return 值时才可以是 non-exhaustive。问题是 with()
函数 做 return 一个值。由于 when
在底部,它的值是 returned 的值,所以在这种情况下它必须是详尽无遗的。
那么,为什么它不坚持 else
分支,即使您省略了“test3”分支?那是因为赋值不会产生值。 (它们的计算结果为 Unit
,这是 Kotlin 对没有 return 有用值的函数的特殊类型。)如果每个分支都给出 Unit
,那么 Kotlin 似乎 * 很高兴推断出默认分支也给出了 Unit
.
但是“test3”分支 return 是其他东西 — myNullableVar
的类型。那么 when
推断出什么类型呢?该类型和 Unit
最接近的公共超类型,即顶级类型 Any?
。 现在 它需要一个明确的 else
分支!
那怎么办?
您找到了几个选项,none 其中最理想的。所以这里还有一些,同上!
您可以 return 来自该分支的显式
Unit
:contains("test3") -> { myNullableVar?.let { it.var3 = "test789" }; Unit }
您可以 return 来自
with()
的显式Unit
:contains("test3") -> myNullableVar?.let { it.var3 = "test789" } } Unit }
您可以为
with()
指定一个明确的类型。 (它有 两个 类型参数,因此您需要同时提供这两个参数,从其参数的类型开始):with<String, Unit>("abc") {
恐怕我还没有找到一个明显的最佳答案……
然后回答你的最后一个问题:是的,?.let{
是完全惯用的,并且对于空值检查很常见。在这种特殊情况下,将其替换为 if
恰好解决了类型问题:
contains("test3") -> { if (myNullableVar != null) myNullableVar.var3 = "test789" }
但是除了 long-winded,如果 myNullableVar
是一个 属性 而不是局部变量,那么它会打开一个竞争条件(如果另一个线程将它设置为null 在测试和赋值之间?)所以编译器会抱怨——这正是人们使用 let
的原因!
(*我找不到此行为的参考资料。有官方说法吗?)