为什么Kotlin中没有使用Void作为返回类型

为什么Kotlin中没有使用Void作为返回类型

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

0_15Pa1eXhWQTTIWNU.png

Kotlin是一种带有很多语法糖的语言。尽管它是一种面向对象的语言。但是在Kotlin中是函数作为一等公民,而不是对象。这一个特性就决定了它可以使用函数进行传递和返回。因此,Kotlin中的高阶函数应用就很广。高阶函数至少就需要一个函数作为参数,或者返回一个函数。

在Kotlin中没有不敢回任何内容的函数。在Java中我们可以使用void来表示函数不返回任何内容,但是在Kotlin中的函数总是要返回一些内容。如果我们没有在明明函数声明中明确的指定返回类型,或者没有在Lambda函数中明确返回任何内容,它就会返回Unit。下面的示例实际时相同的

fun funcionNoReturnAnything(){
	
}
fun funcionNoReturnAnything():Unit{
	
}

或者是在lambda函数体中最后一个值会作为返回值返回,如果没有明确返回,就会默认返回Unit

view.setOnclickListener{
	
}
view.setOnclickListener{
	Unit	
}

尽管他们在写法上会有一些不同,但是Unit同Java中的Void在含义上都是一样的,如果在Kotlin代码中嗲用Java中不会返回任何内容的方法,将返回的是Unit,而不是Void。在Kotlin中Unit是一个单例描述者函数不会返回任何有用的值

我们试着去创建一个Kotlin中的高阶函数,看看反编译背后的Java代码是怎么实现的

fun run(block:() -> Unit){
	block()
}

run函数接受一个名为“block”的参数,该参数具有函数类型**“() -> Unit”**,这意味着块本身是一个不带参数并返回 Unit 的函数。反编译的Java代码如下:

public static final void run(@NotNull Function0 block){
	Instrinsics.checkNotNullParameter(block,"block");
	block.invoke();
}

在底层,函数run采用一个名为block的参数,就像在原始 Kotlin 代码中一样。但是,参数的类型在这里称为“Function0”。由于我们在 Java 中实际上没有函数类型,因此使用智能实现来提供与 Java 的完整互操作性。看源码就可以理解了

public interface Function0<out R>:Funciton<R>{
	public operator fun invoke():R
}

可以看出Fuction0是一个泛型接口,它表示一个不带参数并返回泛型类型 R 的函数类型。该接口有一个方法“invoke”,在调用此函数时会调用该方法。Kotlin 的函数类型被实现为这个通用接口的匿名对象,其中函数体被实现为“invoke”方法的主体。对于参数最多为 22 的函数,还有其他类似的接口。

为了保持与默认情况下没有函数类型并且需要面向对象的方法(创建已定义接口的匿名类的对象)来创建值保存函数的 Java 的互操作性,需要一个类来使编译器能够在下面使用泛型,同时保持“不返回(有用的)值”的概念

此外,每当我们创建 lambda、传递 noinline 函数作为参数或创建对函数类型的引用时,都会创建相应接口的匿名类的对象。每当我们想要传递函数时,Kotlin 都会简单地将我们从 Java 的样板文件中拯救出来。当我们通过在其引用名称后添加括号来调用函数时,将调用前面提到的接口之一的**运算符“invoke”方法。**运算符函数可以通过相应的运算符调用,invoke 函数对应于“invoke operator” =>()。您可以在下面看到两种调用函数类型的方法:

fun run(block:() -> Unit){
	block()
	//或者是使用这种方式都是允许的
	block.invoke()
}

猜你喜欢

转载自juejin.im/post/7112854635836080158