【问题标题】:How can you call different versions of similar extension methods with kotlin如何用 kotlin 调用不同版本的类似扩展方法
【发布时间】:2019-08-12 05:32:25
【问题描述】:

我有以下函数来模拟kotlin的三元运算符

fun Boolean.then(action: () -> Unit): Boolean {
    if (this)
        action.invoke()
    return this
}

fun Boolean.otherwise(action: () -> Unit) {
    if (!this)
        action.invoke()
}

fun <T> Boolean.then(func: () -> T): T? {
    if (this)
        return func.invoke()
    return null
}

fun <T> T?.otherwise(action: () -> T): T {
    return this ?: action.invoke()
}

它们应该像这样使用:

(check).then { doHello() }.otherwise { doWorld() }

val answer = (check).then { "hello" }.otherwise { "world" }

但是,当我尝试使用上述运算符分配值时:

 val visibility: Int = (show).then { View.VISIBLE }.alt { View.GONE }

我收到一条错误消息,说所需的回复是 Int,但它实际上得到了 Unit,这意味着它调用了方法的第一个版本而不是第二个版本

除了重命名方法(当我将前两个更改为 thenDo 否则它是否有效)之外,我是否可以以某种方式编写上述代码,以便编译器知道调用第二个版本?

【问题讨论】:

  • val visibility = if (show) View.VISIBLE else View.GONE 有什么问题?
  • 或者如果您的情况实际上更复杂:yourObject.takeIf { /* complex condition */ }?.let { View.VISIBLE /* or the transformation if condition holds */ } ?: View.GONE /* default value if condition doesn't hold */
  • val 可见性:Int = (show).then { View.VISIBLE }.alt { View.GONE }
  • 如果then的块在某些情况下返回空值,你的代码会编译,但可能不是你想要的。
  • 我对您在这里尝试做的事情感到非常不舒服,这基本上是在 Kotlin 之上构建您自己的语言。这对 DSL 来说很好,但 Kotlin 的 if 表达式已经完全符合您的要求。您的方法使其他开发人员、IDE 和其他工具以及阅读其他人的代码(您肯定必须这样做)更难理解。

标签: kotlin


【解决方案1】:

我认为你不需要两个重载。如果您删除返回 Unit 的那些,那么您的两行代码都可以工作:

(check).then { doHello() }.otherwise { doWorld() }
val answer = (check).then { "hello" }.otherwise { "world" }

这是因为第一行,其中 lambda 表达式返回 Unit,例如doHello(),仍然可以使用thenotherwise 的泛型版本,因为它们仍然被视为具有返回值的函数,即Unit

虽然我同意上面的一些 cmets:你真的需要这个吗?为什么不直接使用if,它是一个返回值的表达式(如三元运算符)。有关更多信息,请参阅讨论 here

【讨论】:

  • 你说得对我可以去掉第一个版本,单元仍然被认为是一个T。至于为什么,我开始它作为一个练习,看看我是否可以做到,现在我只是喜欢语法更好,我也把乐趣改成了中缀,所以我现在可以写(check) then {doThis()} otherwise {doThat()}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-24
  • 2019-06-11
  • 1970-01-01
  • 2016-07-13
  • 2022-01-03
相关资源
最近更新 更多