Kotlin中::对传递函数进行了优化,通俗的说就是函数数值化。
这里我们举个栗子,就看这个熟悉的sortBy排序函数,先定义People类:
//测试代码
data class People(val name: String,val age: Int){
//自定义的排序条件
fun getMax() : Int{
return age * 10 + name.length
}
}
正常使用:
val people = People("zyh",10)
val people1 = People("zyh1",100)
val peopleList = arrayListOf(people,people1)
//给sortBy传入lambda
peopleList.sortBy { people -> people.getMax() }
这里我们给sortBy函数传递一个lambda,由于sortBy函数是内联的,所以传递给它的lambda会被内联,但是假如现在有个问题,就是这些lambda已经被定义成了函数变量,比如我定义了一个顶层函数:
//定义了一个顶层函数
fun getMaxSort(people: People): Int{
return (people.age) * 10 + people.name.length
}
那么排序就变成了:
//调用一遍函数
peopleList.sortBy { getMaxSort(it) }
同样lambda也可以定义成一个变量值:
//排序条件
val condition = { people: People -> people.getMax() }
排序就变成了
//传递参数
peopleList.sortBy(condition)
成员引用 :: 符号来优化一下:
//直接就会调用顶层函数getMaxSort
peopleList.sortBy(::getMaxSort)
//直接就会调用People类的getMax函数
peopleList.sortBy(People::getMax)
看起来就是语法糖,对代码就行了优化。 :: 符号其实就是把函数转换成了一个值,Kotlin支持完整的函数类型,而使用高阶函数可以用lambda。顶层函数getMaxSort(it)是一个函数,但是使用 :: 符号后,::getMaxSort就是一个值了。
需要注意的函数作为值传入时使用 :: 对代码就不用反复输入相同的参数值,对代码进行了优化,但是参数个数、类型、返回值都和其形参必须一致。
fun main(args: Array<String>) {
println(lock("param1", "param2", ::getResult))
}
/**
* @param str1 参数1
* @param str2 参数2
*/
fun getResult(str1: String, str2: String): String = "result is {$str1 , $str2}"
/**
* @param p1 参数1
* @param p2 参数2
* @param method 方法名称
*/
fun lock(p1: String, p2: String, method: (str1: String, str2: String) -> String): String {
return method(p1, p2)
}
这里getResult(str1: String, str2: String)里面的形参类型个数和method: (str1: String, str2: String)必须一直,这样lock调用时第三个参数可直接传入::getResult,无需重复传入参数值。
::后续版本的优化:
//定义一个people实例
val people = People("zyh",10)
//利用成员引用,把函数转换成值
val ageFun = People::age
val age = ageFun(people)
//直接在对象实例上使用 ::
val ageValue = people::age