一、函数类型
在之前我们用到的lambda的语法中val sum: (Int, Int) -> Int = {x: Int, y: Int -> x + y},(Int, Int) -> Int 为函数类型,参数和返回值用 -> 分割开,参数的个数可以是0个或者多个,返回值为空时不可以省略。表示方法可以分为三类。
1.由一个()括起来的参数列表和用->分割的返回类型
() -> Unit //无参,无返回值的函数类型
(T) -> Unit //接收T类型,无返回值的函数类型
(T) -> R //接收T类型、并且返回R类型值的函数类型
(T, R) -> Unit //接收T和R类型参数无返回值的函数类型
(T, R) -> R//接收T和R类型参数,并且返回R类型值的函数类型
2.带有接受者的函数类型,比如 A.(B) -> C 表示在接收者对象A上用参数B调用并返回值C的函数。可以直接使用接受者对象的成员(属性和方法),也可以使用this访问其成员。和扩展函数很类似。(kotlin鼓励使用扩展函数,当我们要创建一个用于某个对象的函数时,可以考虑使其成为一个以该对象为接收者的扩展函数。为了尽量减少 API 污染,尽可能地限制扩展函数的可见性。根据需要,使用局部扩展函数、成员扩展函数或者具有私有可视性的顶层扩展函数。)
带与不带接受者的函数类型可以互换,接收者可以最为第一个参数,反之亦然。例如 (A, B)->C 类型的值可以赋值给接收A.(B)->C类型地方,反之亦然。
fun Person.getNextYearAge2(): Int {
return age + 1
}
fun getAge(block: (Person) -> Int): Int {
return block(Person(12, "A"))
}
fun main(args: Array<String>) {
val age = getAge(Person::getNextYearAge2)
}
3.挂起函数属于特殊种类的函数类型,它的表示法中有一个 suspend 修饰符 ,例如 suspend () -> Unit
或者 suspend A.(B) -> C
。
Tips:(1)函数类型可空时使用()? ((Int, Int) -> Int)?
(2)函数类型是右结合的 (Int)-> ((Int) -> Unit)) 等价于 (Int) -> (Int) -> Unit 而不等价于((Int) -> (Int))-> Unit
二、 类型别名 使用关键词 typealias
typealias lambdaAlias = (Int) -> Boolean
当某个函数类型被多次引用时可以使用函数别名。声明函数类型别名不会产生新的变量
三、函数类型实例化
实例化的函数类型可以作为参数传递到函数中,函数实例化的方式常用的有三种。
(1)使用函数字面值的代码块,lambda表达式或者匿名函数
lambda表达式 :{a, b -> a+b}
fun getInt(block: (String) -> Int) {
//...
}
getInt { it.toIntOrNull() ?: 0 }
匿名函数:fun (s: String): Int { return s.}
fun getInt(block: (String) -> Int) {
//...
}
getInt(fun(s: String): Int { return s.toIntOrNull() ?: 0 })
匿名函数可以指定返回类型(大部分情况下lambda返回类型可以自动推到),匿名函数不能写到()外边。一个不带标签的return会在fun关键词声明的函数中返回。因此lambda表达式会在包含他的函数中返回(只有内联函数中才能使用不带标签的retuen),匿名函数中return将会在自身返回。
(2)使用已有声明的可调用引用
当我们已经有对应函数类型的函数时,可以使用成员引用将一个函数转换成一个值来传递。
- 顶层、局部、成员、扩展函数:
::isOdd
、String::toInt
, - 顶层、成员、扩展属性:
List<Int>::size
, - 构造函数:
::Regex
fun Person.getNextYearAge2(): Int {
return age + 1
}
fun getNextYearAge(person: Person): Int {
return person.age + 1
}
fun getAge(block: (Person) -> Int): Int {
return block(Person(12, "A"))
}
fun main(args: Array<String>) {
print("A next year age = ${getAge(::getNextYearAge)}")
val age = getAge(Person::getNextYearAge2)
}
(3)使用实现函数类型接口的自定义类的实例
class IntTransformer: (Person) -> Int {
override fun invoke(p1: Person): Int {
TODO("Not yet implemented")
}
}
fun getAge(block: (Person) -> Int): Int {
return block(Person(12, "A"))
}
fun main(args: Array<String>) {
print("A next year age = ${getAge(IntTransformer())}")
}
三、SAM转换 (Single Abstract Method Conversions)
四、内联函数 inline