我仍然在学习Kotlin,并试图了解其核心原则 . 我没有得到的是:
fun x() : Int { return 10 }
val y : () -> Int = ::x
val z : () -> Int = { 10 }
fun main(args: Array<String>) {
println(::x)
println(y)
println(z)
}
我们得到以下输出:
fun x(): kotlin.Int
fun x(): kotlin.Int
() -> kotlin.Int
我的问题是为什么输出不一样(我相信这些功能应该可以互换,相当)?我认为所有函数的类型应该是 () -> Int
. 为什么我们将原始名称与函数签名( fun x
)保持在一起,即使它被分配给另一个名称( y
)?是否有任何语言设计原则需要功能签名的这种差异?
还有一个额外的问题 - 为什么我们需要使用运算符 ::
. 没有它就无法编译 . 但为什么语言设计需要这个?不会 val y = x
工作得很好而且更简单吗?
3 回答
fun x()
是来自过程编程的普通命名函数 .val y
是一个包含对x
的引用的属性 .val z
是函数式编程的匿名函数 .::
是'function reference',是程序编程和函数编程之间的一种桥梁 .默认情况下,您的函数应为
fun
. 另一方面,Lambda表达式(匿名函数)旨在作为回调传递给其他函数 .IF 你从我的角度思考,我认为你可以立即理解它 .
x
只是标识符而不是变量,因此您无法直接引用它 .fun x()
是一个派生自Function0
的类 .表达式
::x
是fun x()
类型的实例,在kotlin中称为function reference expression .有时函数在kotlin中有自己的类,就像java-8 lambda表达式一样 . 但function reference expression不能与diff receiver一起使用 .
当调用inline function后跟一个lambda时,lambda和函数都将在调用站点内联 . 但是使用非内联function reference expression进行呼叫,只有inline function将在呼叫站点内联 .
我想更好地理解字节码
y和z值的类型为Function0
x的类型为MainKt $ main $ 1
在每种情况下(println),我们只显示方法声明(可见性修饰符,返回类型,签名)而不调用 . y和z是高阶函数,在字节码中由Function0类表示,对于x值,它只是静态函数 .
当您调用
println(::x) println(y) println(z)
时,您只需打印函数声明 . 这没关系,x和y函数的声明与z函数的声明不同 . 因为y引用了x函数,而z仍然是返回10的高阶函数 . 简单来说y == x,因为你从x赋值给y函数声明 . 只是为了注意 . 在Java中,我可以用这种方式显示方法声明:结论:在您的代码中,您只需打印函数返回类型,可见性修饰符和签名 .