【问题标题】:Can I add return when I use Elvis operation in Kotlin?在 Kotlin 中使用 Elvis 操作时可以添加 return 吗?
【发布时间】:2018-02-28 22:55:10
【问题描述】:

我在http://mings.in/2017/03/12/Kotlin-Null-Safety.html阅读了猫王接线员

Code A 和 Code C 都可以,但是 Code B 出错(“Type mismatch: inferred type is Int but Unit was expected”),为什么?

代码 A

override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)  

      val b: String?  = "hello"
      val l = b?.length ?: -1
 }

代码 B

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      val b: String?  = "hello"
      val l = b?.length ?: return -1

    }

代码 C

 fun getLength(b: String?): Int {
        val l = b?.length ?: return -1       
        return l
    }

顺便说一句,BakaWaii 告诉我“代码 A 没问题,因为 -1 是一个表示值的表达式,因此可以将它分配给 l。但是在代码 B 中,return -1 是一个从函数返回的表达式。 "

我无法理解“在代码 B 中,return -1 是从函数返回的表达式”。我认为“返回-1”将返回-1,为什么应用程序会出现“类型不匹配:推断类型为Int但预期单位”?

还有更多:

代码C和代码B一样,不知道为什么还可以!!!

【问题讨论】:

  • 当您尝试编译或运行它时会发生什么?这会给你答案。

标签: kotlin


【解决方案1】:

来自Kotlin's doc

如果?:左边的表达式不为null,则elvis运算符返回,否则返回右边的表达式。请注意,由于 throwreturn 在 Kotlin 中是表达式,因此它们也可以用在 elvis 运算符的右侧。

also

return。默认从最近的封闭函数或匿名函数返回。

所以,答案是肯定的,只要封闭函数的返回类型与返回值匹配即可,例如:

fun getLength(b: String?): Int {
    val l = b?.length ?: return -1    //return an `Int`
    //if return -1, the code below will not execute
    return l
}

请注意,代码 A 和代码 B 在控制流上是不同的。如果您在左侧值为 null 时尝试分配替代/默认值,代码 A 将是最好的方法。

【讨论】:

  • 谢谢!但是当我使用代码 B 时出现错误“类型不匹配:推断类型为 Int 但预期单位”
  • 封闭函数的返回类型应与返回值匹配。请参见上面的示例。 getLength()的返回类型为Int,返回值为-1。这里的return 从最近的封闭函数返回,但没有为l 赋值。
  • 但是为什么代码 A 可以?
  • 还有更多 val l = b?.length ?: {return -1} is not OK
  • 代码 A 可以,因为-1 是一个表示值的表达式,因此可以将其分配给l。但在代码 B 中,return -1 是一个从函数返回的表达式。
【解决方案2】:

Code ACode B 之间的区别是,第一个设置 -1 到您的变量(现在是 l),第二个设置 -1 作为函数工作的结果。并且Type mismatch 错误消息说函数不应该返回任何值(或返回Unit)但你试图返回 int - 所以它不是 Elvis 运算符语法错误。

然后,如果您将 Code B 放在某个 Int 函数中(就像您在 Code C 中所做的那样),就不会出现任何错误。

示例

如果你想将Int“转换”为StringBuilder,你可以这样做:

fun toStringBuilder(i: Int?): StringBuilder {
    val result = i?.toString() ?: ""
    return StringBuilder(result)
}

猜猜没有问题。

第二个例子也完全正确。

fun toStringBuilder(i: Int?): StringBuilder {
    val result = i?.toString() ?: return StringBuilder()
    return StringBuilder(result)
}

如果参数值为null,函数将不会到达第二行,因为它会首先返回。

第三个例子会产生错误(比如你的Code B)。

fun toStringBuilder(i: Int?): StringBuilder {
    val result = i?.toString() ?: return ""
    return StringBuilder(result)
}

同样没有语法错误。猫王运营商是正确的。错误是因为您试图将 String 返回到声明为返回 StringBuilder 的函数。

【讨论】:

  • 谢谢! Code B 很难看懂,能不能给我写一个 Code B 的等价代码?
  • @HelloCW 在我的回答中添加了示例。
  • 谢谢!现在我完全明白了。之前我认为"return -1" 会给代码 B 中的 var l 赋值 -1,实际上是给函数 onCreate(savedInstanceState: Bundle?) 赋值 -1,而 Android studio 并没有给出更详细的错误信息。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 2017-04-27
  • 2012-04-15
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多