【问题标题】:How would I write this in idiomatic Kotlin?我将如何用惯用的 Kotlin 写这个?
【发布时间】:2018-04-12 21:54:53
【问题描述】:

我有一些代码:

private fun getTouchX(): Int {
    arguments ?: return centerX()

    return if (arguments.containsKey(KEY_DOWN_X)) {
        arguments.getInt(KEY_DOWN_X)
    } else {
        centerX()
    }
}

private fun centerX() = (views.rootView?.width ?: 0) / 2

我想缩短它。

在getTouchX函数中,有两个重复的返回条件。 (即centerX)

我尝试过这样做:

 private fun getTouchX(): Int {
    if (arguments == null || !arguments.containsKey(KEY_DOWN_X)) {
        return centerX()
    }
    return arguments.getInt(KEY_DOWN_X)
}

然而,它看起来更像 Java 而不是 Kotlin。

我怎么能用惯用的 Kotlin 写这个?

【问题讨论】:

标签: kotlin


【解决方案1】:

我不确定参数的来源,但更简洁的解决方案应该是

private fun getTouchX(): Int =
    if(arguments?.containsKey(KEY_DOWN_X) == true) {
        arguments.getInt(KEY_DOWN_X)
    } else {
        centerX()
    }

if 仅在arguments 为非空时调用containsKey,否则== 的左侧解析为nullnull != true,所以它会从 else 返回 centerX()

同样,如果 arguments 不为 null,则 containsKey 的结果将用于解析。

现在只有一个表达式,可以使用正文表达式格式。

【讨论】:

  • 我对此有更改答案。因为 getInt 不返回 null。所以使用 containsKey 是必要的。谢谢@Mikezx6r
【解决方案2】:

我可能会使用带有when 表达式的表达式函数:

private fun getTouchX() = when {
   arguments == null || !arguments.containsKey(KEY_DOWN_X) -> centerX()
   else -> arguments.getInt(KEY_DOWN_X)
}

您也可以考虑将touchX 声明为private val

private val touchX: Int
    get() = when {
       arguments == null || !arguments.containsKey(KEY_DOWN_X) -> centerX()
       else -> arguments.getInt(KEY_DOWN_X)
    }

【讨论】:

  • ,-syntax 已被弃用,最好使用||null-checking 的这种方式也是 Java 风格的祸根;)
  • 好点,它短路了 1 条线。但是arguments == null 这对我来说看起来很长。 (个人感觉)。不过谢谢!
  • @leoderprofi :你在哪里读到逗号作为模式分隔符已被弃用?在 Kotlin 参考资料中找不到任何提及。至于空值检查的方式,Kotlin 不是 Java,只要空值检查传播正确就绝对安全,而且我认为它比使用 == true 进行空值检查更清晰。
  • Android Studio 在没有参数的情况下会发出警告。我花了一段时间才通过sourceIssue KT-5143 追踪到这一点。我从不喜欢 java 中的所有 null 检查,b == true for b : Boolean? 表达式 is an idiom(在最底部)
  • @leoderprofi :嗯,看来你是对的。 when { ... } 不鼓励使用逗号作为模式分隔符(但 when(...) { ... } 不鼓励使用逗号)。奇怪的是参考文献中没有提到它。
【解决方案3】:

只看简单的 Kotlin 代码,我的建议是:

    private fun getTouchX() =
        arguments?.let {
            if (!it.containsKey(KEY_DOWN_X))
                return@let null
            it.getInt(KEY_DOWN_X)
        } ?: centerX()

但如果 arguments 是 Android BaseBundle 的后代,您可能会进一步将其压缩为:

private fun getTouchX() = arguments?.getInt(KEY_DOWN_X, centerX()) ?: centerX()

注意:由于方法签名看起来像是在读取属性,因此您可以考虑将其转换为只读属性。

【讨论】:

    猜你喜欢
    • 2018-09-25
    • 1970-01-01
    • 2023-03-07
    • 2018-11-21
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    相关资源
    最近更新 更多