【问题标题】:Kotlin's 'let' plus elvis, and accidental null return valuesKotlin 的 'let' 加上 elvis,以及意外的 null 返回值
【发布时间】:2019-04-24 07:38:36
【问题描述】:

今天我很惊讶地发现,这种显然是惯用的代码的做法失败了:

class QuickTest {

    var nullableThing: Int? = 55

    var nullThing: Int? = null

    @Test
    fun `test let behaviour`() {
        nullableThing?.let {
            print("Nullable thing was non-null")
            nullThing?.apply { print("Never happens") }
        } ?: run {
            fail("This shouldn't have run")
        }
    }
}

这是因为,结合隐式返回,nullThing?.apply{...} 将 null 传递给 let,因此 elvis 运算符对 null 求值并运行第二个块。

这很难检测到。除了传统的if/else 之外,我们是否有合适的替代方案而没有这个陷阱?

【问题讨论】:

    标签: kotlin idioms


    【解决方案1】:

    您可以使用also 代替letalso 将返回 nullableThing,而 let 将返回 lambda 返回的任何内容。

    请参阅这篇文章:https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84(点“3. 返回 this 与其他类型”)。

    【讨论】:

      【解决方案2】:

      您的案例是also 主题的候选者。比较两个block 操作:

      fun <T> T.also(block: (T) -> Unit): T
      fun <T, R> T.let(block: (T) -> R): R
      
      nullableThing?.also {
          print("Nullable thing was non-null")
          nullThing?.apply { println("Never happens") }
      } ?: run {
          fail("This shouldn't have run")
      }
      

      另一种惯用方式是使用when 语句

      when (nullableThing) {
          null ->
              print("Nullable thing was non-null")
              nullThing?.apply { println("Never happens") }
          else -> fail("This shouldn't have run")
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-24
        • 2013-04-26
        相关资源
        最近更新 更多