一 泛型函数
函数的参数类型一般在函数定义的时候就规定了的,但是如果在使用的时候才能确定具体使用什么参数类型,这个要如何解决呢?泛型函数解决这个问题
定义泛型函数时,要在函数名之前加上这个符号,表明声明T类型的参数,具体确认在函数使用中给泛型T赋予确切值既可
fun <T> fanxing(tag:String,vararg args:T):T?{
var a : T? = null
for (item in args){
a = item
Log.d("fanxing","$tag : $item")
}
return a
}
二 内联函数
举个例子,如果我们想接受泛型类型下的子类,比如number泛型类型,想接受它的子类:Int,double,Float类型,此时再用下面的泛型函数只能接受number类型
fun fanxing(tag:String,vararg args:Number):Number?{
var a : T? = null
for (item in args){
a = item
Log.d("fanxing","$tag : $item")
}
return a
}
如果想接受其子类类型,就要用到内联函数
inline fun <reified T : Number> fanxing(tag:String,vararg args:Number):Number?{
var a : T? = null
for (item in args){
a = item
Log.d("fanxing","$tag : $item")
}
return a
}
内联函数在编译的时候,会在调用处把该函数的内部代码直接复制一份,调用几次就复制几次,而非普通函数那样仅仅是提供一个函数地址
三 高阶函数
上面说的函数的入参都是对象类型,而高阶函数可以传入其他的函数作为入参;熟练使用高阶函数,可以达到让你意想不到的效果。
比如:对于一个数组变量,如果我们想获得这个数组变量的最大值,我们可以调用这个数组变量的max()方法,但是如果这个数组变量是字符串数组,比如arrayOf(“How”, “do”, “you”,“do”, "I’m ", “Fine”),此时调用max函数得到的并不是字符长度最长的那个字符,而是在字母表最靠后的那个字符串(you)。当然我们也可以重新写一个函数,改变其算法,但是如果我们那天需要其他比较大小的算法,难道又要再写一个函数?所以Kotlin就有一个高阶函数,直接把比较函数作为参数传入,由开发者再调用高阶函数的时候来选择具体的算法函数传入即可
fun <T> maxCustom(array:Array<T>,greater:(T:T) ->Boolean):T?{
var max : T? = null
for (item in array){
if(max == null || greater(item,max) ){
max = item
}
}
return max
}
var string_array:Array<String> = arrayOf("How", "do", "you", "do", "I'm ", "Fine")
maxCustom(string_array,
//比较值的大小
{
a,b -> a>b
});
var string_array:Array<String> = arrayOf("How", "do", "you", "do", "I'm ", "Fine")
maxCustom(string_array,
//比较长度的大小
{
a,b -> a.length>b.length
});
这里传入的函数用{ }包起来,这里用到了Lambda的匿名函数的写法;此时利用高阶函数,我们可以选择性的选择不同算法函数传入,达到效果
四 扩展函数
使用java开发的时候,虽然系统自带的类提供了很多方法,但是还是无法满足所有的业务要求,此时就要写一个个工具类,这样会使工具类越来越多,越来越难以管理。此时kotlin就推出了扩展函数。扩展函数是让开发者给系统api提供补写的机会;比如数组工具类里有比较大小的max()和排序的sort(),但是没有交换的方法,此时可以用扩展函数给数组工具类加入排序的功能函数
fun Array<Int>.swap(pos1: Int, pos2: Int) {
val tmp = this[pos1] //this表示数组变量自身
this[pos1] = this[pos2]
this[pos2] = tmp
}
但是这只是针对Int数组类型的工具类,如果要满足所有类型的,此时就要需要引入上面说过的泛型函数的概念
fun <T> Array<T>.swap(pos1: Int, pos2: Int) {
val tmp = this[pos1] //this表示数组变量自身
this[pos1] = this[pos2]
this[pos2] = tmp
}
有了扩展函数,数组变量就可以直接调用新增的swap方法,仿佛是系统自带的函数一样,一下是swap函数的使用案例:
val array:Array<Double> = arrayOf(1.0, 2.0, 3.0, 4.0, 5.0)
btn_function_extend.setOnClickListener {
//下标0,3的数组元素交换
array.swap(0, 3)
}