Kotlin高阶函数--Higher-Order Function
参数或者返回值为函数类型的函数,在Kotlin中被称为高阶函数。
高阶函数概念源自数学中的高阶函数-在数学中,如果一个函数使用函数作为他的参数或者结果,则他被称为高阶函数。
Java中函数的参数不能是函数
Kotlin中函数可以含有函数类型的参数,且函数的返回值也可以是函数类型
SAM接口--Single Abstract Method
只有一个抽象方法的接口简称SAM接口
函数类型的参数示例
无参数无返回值:(()->Unit)
单Int型参数返回:String(Int->String)
双冒号::method是什么?(函数引用Function Reference)
::method这种写法叫做函数引用;(method在加上::就变成了一个和函数具有相同功能的对象了)
-
对于一个已经声明好的函数,不管是要把它作为参数传递给函数,还是把它赋值给变量,都需要在函数名的左边加上双冒号
a(::b) val d = ::b
-
在Kotlin中,一个函数名的左边加上双冒号,它就不表示这个函数本身了,而是表示一个对象,或者是一个指向对象的引用,但是这个对象并不是函数本身,而是和函数具有相同功能的对象
b(1) // 调用函数 d(1) // 用对象 a 后面加上括号来实现 b() 的等价操作 (::b)(1) // 用对象 :b 后面加上括号来实现 b() 的等价操作
-
函数类型的对象和普通对象的区别:
普通类型的对象无法通过对象()这种方法来调用,但是函数类型的对象是可以的,但是这其实是个假的调用,它是Kotlin的语法糖。
对一个函数类型的对象加括号,加参数,真正调用的是这个对象的invoke()函数
d(1) // 实际上会调用 d.invoke(1) (::b)(1) // 实际上会调用 (::b).invoke(1) //错误写法,对一个函数调用invoke b.invoke(1)
双冒号加函数名是一个指向对象的引用,但是并不是指向函数本身。而是指向一个看不见的对象,这个对象复制了原函数的功能,但它并不是原函数
Kotlin中的匿名函数(其实是一个对象,并不是一个函数)
简单来说就是没有名字的函数,本质是一个对象
a(fun(param: Int): String {
return param.toString()
});
val d = fun(param: Int): String {
return param.toString()
}
//错误写法,左右两边都有名字,Kotlin是不允许的
val d = fun a(param:Int):String{
}
Java中和Kotlin中接口回调设计及使用对比
-
Java
//定义 public interface OnClickListener { void onClick(View v); } public void setOnClickListener(OnClickListener listener) { this.listener = listener; } //使用 view.setOnClickListener(new OnClickListener() { @Override void onClick(View v) { switchToNextPage(); } });
-
Kotlin
//定义 public interface OnClickListener { void onClick(View v); } fun setOnClickListener(onClick: (View) -> Unit) { this.onClick = onClick } //使用 view.setOnClickListener(fun(v: View): Unit) { switchToNextPage() }) //使用lambda替换 view.setOnClickListener({ v: View -> switchToNextPage() })
Lambda表达式
-
Lambda表达式示例:
(parameters) -> expression 或 (parameters) ->{ statements; } // 1. 不需要参数,返回值为 5 () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 (int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s)
-
当Lambda是函数的最后一个参数,或唯一参数,或单参数时的不同写法
//Lambda是函数的最后一个参数,可以把Lambda写在括号外面 view.setOnClickListener() { v: View -> switchToNextPage() } //Lambda是函数的唯一参数,直接将()去掉 view.setOnClickListener { v: View -> switchToNextPage() } //如果Lambda中函数时单参数的,参数也可以省略不写 view.setOnClickListener { switchToNextPage() } //如果Lambda中函数时多个参数,但是部分参数不需要使用时 mAdapter.setOnItemClickListener { _, _, position -> SocietyHomeAct.toSocietyHome(this, (mAdapter.getItem(position))) }
Kotlin对于省略的唯一参数有默认名字:it
Lamda的返回值不是用return返回,而是直接取最后一行代码的值
-
将匿名函数赋值给变量而不是作为函数参数传递的时候的写法
val b = fun(param: Int): String { return param.toString() } //简写成Lambda val b = { param: Int -> return param.toString() } //错误写法 val b = { return it.toString() // it 报错,因为无法根据上下文推断对象 } //替代方案:给左边的变量指明类型 val b: (Int) -> String = { //错误写法:Lambda的返回值不能用return返回,会直接取最后一行作为返回值 //return it.toString() // it 可以被推断出是 Int 类型 it.toString() // it 可以被推断出是 Int 类型 }
Kotlin里的函数和匿名函数以及Lambda表达式的本质
它们都是函数类型的对象
函数:用来实现特定功能的代码块
匿名函数:不是一个函数,是一个具备与函数功能相同的对象
Lambda:不是一个函数,是一个函数类型的对象
使用时能怎么使用双冒号加函数名就能怎么使用匿名函数,以及怎么使用Lambda表达式。
Kotlin中的Lambda和Java8的Lambda区别
Java从8开始引入了Lambda支持,主要作用是对于单抽象方法的接口,Java 8允许你用Lambda表达式来创建匿名类对象,但是它本质上还是创建了一个匿名类对象,只不过是一种简化的写法。
Kotlin中的Lambda是实实在在的函数类型的对象,功能更强,写法更多更灵活,
- Kotlin中的Lambda是函数类型的对象
- Java 8中的Lambda只是一种便捷的写法,在功能上没有突破
总结
1、在Kotlin中,有一类Java不存在的类型,叫函数类型,这类对象可以当函数来使用的同时,还可以作为函数的参数,函数的返回值,以及赋值给变量
-
2、创建一个函数类型的对象的三种方式
::b//双冒号加函数名 val b = fun(){}//匿名函数 val c = {}//Lambda
3、双冒号加函数名、匿名函数和Lambda本质都是函数类型的对象;在Kotlin中,匿名函数不是函数,Lambda也只是代码块,Kotlin的Lambda可以归为函数类型的对象。