📜  Kotlin 中的函数返回和类型层次结构

📅  最后修改于: 2022-05-13 01:55:17.383000             🧑  作者: Mango

Kotlin 中的函数返回和类型层次结构

Kotlin 是 JetBrains 开发的一种静态类型的通用编程语言,构建了 IntelliJ IDEA、PhpStorm、App code 等世界级的 IDE。它由 JetBrains 于 2011 年首次推出,是一种新的 JVM 语言。 Kotlin 是一种面向对象的语言,是一种比Java“更好的语言”,但仍可与Java代码完全互操作。

类型层次结构

所有类型的 Kotlin 对象都组织成子类型/超类型关系的层次结构。 Any 相当于 Java 的 Object 类。在 Kotlin 中,最上面的类型称为 Any。这类似于 Java 的对象类型。 Any 类型定义了众所周知的 toString、hashCode 和 equals 方法。它还定义了扩展方法 apply、let 和 to 等。高阶函数和函数式编程。 Unit 类型相当于Java中的 void 。 Unit 类型在函数式编程语言中很常见,void 和 Unit 之间的区别很微妙。 Void 不是一种类型,而是一种特殊的边缘情况,用于向编译器指示函数不返回值。 Unit 是一个适当的类型,带有一个单例实例,也称为 Unit 或 ()。

当函数被定义为返回单元时,它将返回单例单元实例。这导致类型系统更加健全,因为现在所有函数都可以定义为具有返回值,即使它只是 Unit 类型,并且没有参数的函数可以定义为接受 Unit 类型。 Kotlin 与Java最显着的不同之处在于添加了一个底层类型 Nothing,它是一种没有实例的类型。类似于 Any 是所有类型的超类,Nothing 是所有类型的子类。对于那些不熟悉底部类型概念的人来说,拥有这种类型可能看起来很奇怪,但它有几个用例。

首先, Nothing可以用来通知编译器一个函数永远不会正常完成;例如,它可能永远循环,或者总是抛出异常。另一个例子是空的不可变集合。可以将空的 Nothing 列表分配给除字符串列表之外的引用,并且由于该列表是不可变的,因此不存在将字符串添加到此类列表的危险。因此,这些空值可以被缓存和重用。这实际上是标准库函数emptyList()、emptySet()等实现的基础。

函数返回

要从函数返回一个值,我们使用 return 关键字和我们想要返回的值或表达式:

Kotlin
fun addTwoNumbers(a: Int, b: Int): Int {
  return a + b
}


Kotlin
fun largestNumber(a: Int, b: Int, c: Int): Int {
  fun largest(a: Int, b: Int): Int {
    if (a > b) return a
    else return b
  }
  return largest(largest(a, b), largest(b, c))
}


Kotlin
fun printLessThanTwo() {
  val list = listOf(1, 2, 3, 4)
  list.forEach(fun(x) {
    if (x < 2) println(x)
    else return
  })
  println("This line will still execute")
}


Kotlin
fun printUntilStop() {
  val list = listOf("a", "b", "stop", "c")
  list.forEach stop@ {
    if (it == "stop") return@stop
    else println(it)
  }
}


Kotlin
fun printUntilStop() {
  val list = listOf("a", "b", "stop", "c")
  list.forEach {
    if (it == "stop") return@forEach
    else println(it)
  }
}


请注意,我们指定了函数的返回值。默认情况下,return 从最近的封闭函数或匿名函数返回。因此,在嵌套函数中,这将仅从最里面的函数返回:

科特林

fun largestNumber(a: Int, b: Int, c: Int): Int {
  fun largest(a: Int, b: Int): Int {
    if (a > b) return a
    else return b
  }
  return largest(largest(a, b), largest(b, c))
}

在这个有点做作的例子中,嵌套函数最大只从自身返回。如果最里面的函数是一个匿名函数,那么这仍然算作返回目的:

科特林

fun printLessThanTwo() {
  val list = listOf(1, 2, 3, 4)
  list.forEach(fun(x) {
    if (x < 2) println(x)
    else return
  })
  println("This line will still execute")
}

如果我们需要从闭包中返回一个值,那么我们需要用标签限定返回,否则,返回将用于外部函数。标签只是一个以@结尾的字符串:

科特林

fun printUntilStop() {
  val list = listOf("a", "b", "stop", "c")
  list.forEach stop@ {
    if (it == "stop") return@stop
    else println(it)
  }
}

我们不需要指定标签,在这种情况下可以使用隐式标签。隐式标签是接受闭包的函数的名称。如果定义了标签,则不会生成隐式标签:

科特林

fun printUntilStop() {
  val list = listOf("a", "b", "stop", "c")
  list.forEach {
    if (it == "stop") return@forEach
    else println(it)
  }
}