功能参考

我们可以通过在函数的名称前加上::来引用函数而不实际调用它。然后可以将其传递给接受一些其他函数作为参数的函数。

fun addTwo(x: Int) = x + 2
listOf(1, 2, 3, 4).map(::addTwo) # => [3, 4, 5, 6]

没有接收器的函数将转换为 (ParamTypeA, ParamTypeB, ...) -> ReturnType,其中 ParamTypeAParamTypeB …是函数参数的类型,`ReturnType1 是函数返回值的类型。

fun foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
    //...
}
println(::foo::class.java.genericInterfaces[0]) 
// kotlin.jvm.functions.Function3<Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo0, Foo1, Foo2) -> Bar

带接收器的函数(无论是扩展函数还是成员函数)具有不同的语法。你必须在双冒号之前添加接收器的类型名称:

class Foo
fun Foo.foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
    //...
}
val ref = Foo::foo
println(ref::class.java.genericInterfaces[0]) 
// kotlin.jvm.functions.Function4<Foo, Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo, Foo0, Foo1, Foo2) -> Bar
// takes 4 parameters, with receiver as first and actual parameters following, in their order

// this function can't be called like an extension function, though
val ref = Foo::foo
Foo().ref(Foo0(), Foo1(), Foo2()) // compile error

class Bar {
    fun bar()
}
print(Bar::bar) // works on member functions, too.

但是,当函数的接收器是一个对象时,接收器在参数列表中被省略,因为它们只是这种类型的一个实例。

object Foo
fun Foo.foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
    //...
}
val ref = Foo::foo
println(ref::class.java.genericInterfaces[0]) 
// kotlin.jvm.functions.Function3<Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo0, Foo1, Foo2) -> Bar
// takes 3 parameters, receiver not needed

object Bar {
    fun bar()
}
print(Bar::bar) // works on member functions, too.

从 kotlin 1.1 开始,函数引用也可以绑定到一个变量,然后称为有界函数引用

Version >= 1.1.0

fun makeList(last: String?): List<String> {
    val list = mutableListOf("a", "b", "c")
    last?.let(list::add)
    return list
}

请注意,此示例仅用于显示有界函数引用的工作原理。所有其他感官都是不好的做法。

但是有一个特例。无法引用声明为成员的扩展函数。

class Foo
class Bar {
    fun Foo.foo() {}
    val ref = Foo::foo // compile error
}