【问题标题】:How to do guard let statement in Kotlin like Swift?如何像 Swift 一样在 Kotlin 中做 guard let 语句?
【发布时间】:2019-04-13 20:40:35
【问题描述】:

我想像 Swift 一样在 Kotlin 中编写 guard let 语句。

例如:

guard let e = email.text , !e.isEmpty else { return }

任何建议或示例代码?

【问题讨论】:

标签: kotlin


【解决方案1】:

试试

val e = email.text?.let { it } ?: return

说明:这会检查属性email.text 是否不是null。如果它不为空,它分配值并移动到执行下一条语句。否则它会执行return 语句并中断该方法。

编辑:按照@dyukha 在评论中的建议,您可以删除多余的let

val e = email.text ?: return

如果要检查任何其他条件,可以使用 Kotlin 的 if 表达式。

val e = if (email.text.isEmpty()) return else email.text

或尝试(如@Slaw 建议的那样)。

val e = email.text.takeIf { it.isNotEmpty() } ?: return

您可能还想尝试这里实现的guard 函数:https://github.com/idrougge/KotlinGuard

【讨论】:

  • 为什么不只是email.text ?: return
  • 同意@dyukha。更甜!
  • 但问题中的条件不同,不是吗?我不太明白guard let 是做什么的,但似乎你应该检查email.text 是否为空,而不是与null 比较。
  • 更新了我的答案。
  • 如果还想使用elvis算子,可以使用:val e = email.text.takeIf { it.isNotEmpty() } ?: return
【解决方案2】:

试试

val e = email.text ?: run {
    // do something, for example: Logging
    return@outerFunction
}

如果你想在return之前做点别的事情。

【讨论】:

  • 这是最好的答案,但并不完美,因为 let 没用。 val e = email.text ?: run { // 做一些事情,例如:Logging return@outerFunction }
  • 看起来很有希望的语法我必须尝试。
【解决方案3】:

我用过这个:

it ?: return

简单而简短

【讨论】:

  • 请注意,此解决方案不适用于 email.text 等可变字段。
【解决方案4】:

我有一个稍微不同的解决方案,如果您希望重新创建 swift 具有解包多个选项然后使用解包变量的能力。

考虑在 Kotlin 文件中添加这些行


    inline fun <T1, T2, T3, R> guard(
        p1: T1?, p2: T2?, p3: T3?,
        condition: Boolean = true,
        block: (T1, T2, T3) -> R
    ): R? = if (p1 != null && p2 != null && p3 != null && condition)
        block(p1, p2, p3)
    else null

    inline fun <T1, T2, T3, T4, R> guard(
        p1: T1?, p2: T2?, p3: T3?, p4: T4?,
        condition: Boolean = true,
        block: (T1, T2, T3, T4) -> R
    ): R? = if (p1 != null && p2 != null && p3 != null && p4 != null && condition)
        block(p1, p2, p3, p4)
    else null

(我确实有 p9,但为简洁起见保存了它)

这意味着你现在做

    //given you have 

    var firstName: String? = null
    var lastName: String? = null
    var email: String? = null
    var password: String? = null

    fun createUser(name: String, lname: String, mail: String, pword: String) {
    // some work            
    }

你现在可以像这样使用它

    guard(firstName, lastName, email, password){ fName, lName, mail, pword ->            
        createUser(fName, lName, mail, pword) // all your variables are unwrapped!
    } ?: return // <- here if you want an early return

    // or
    guard(firstName, lastName, email, password,
        condition = email.isValid 
    ) { fName, lName, mail, pword -> 
        // N.B this will not execute if the email is not valid
        createUser(fName, lName, mail, pword)
    }

由于这个函数是内联的,你可以在协程中使用它,你可以从block返回一个值并使用它。

【讨论】:

    【解决方案5】:

    我找到了另一种方法。只需创建以下函数:

    inline fun <T: Any> T?.guard(block: () -> Unit): T {
        if (this == null) block(); return this!!
    }
    

    那么你可以这样使用它:

    val date: Date?
    date = Date()
    val nonNullableDate = date.guard { return }
    

    nonNullableDate 的类型为 Date

    无论如何,因为它不是像在 swift 中那样创建变量,NullPointerExceptions 是可能的

    希望 Kotlin 将来会添加 guard 关键字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 2022-09-30
      • 1970-01-01
      相关资源
      最近更新 更多