高阶函数
高阶函数是以另一个函数作为参数 and/or 返回函数的函数。
将函数作为参数
1 2 3 4 5 6 7 8 9 10 11 fun calculate (x: Int , y: Int , operation: (Int , Int ) -> Int ) : Int { return operation(x, y) } fun sum (x: Int , y: Int ) = x + y fun main () { val sumResult = calculate(4 , 5 , ::sum) val mulResult = calculate(4 , 5 ) { a, b -> a * b } println("sumResult $sumResult , mulResult $mulResult " ) }
声明一个高阶函数。它接受两个整数参数 x 和 y。此外,它还接受另一个函数操作作为参数。声明中还定义了操作参数和返回类型。
高阶函数返回包含所提供参数的操作调用结果。
声明与操作签名匹配的函数。
调用高阶函数传入两个整数值和函数参数 ::sum
。::s
是在 Kotlin 按名称引用函数的符号。
调用传入 lambda 的高阶函数作为函数参数,看起来会更清楚。
返回函数
1 2 3 4 5 6 7 8 9 10 fun operation () : (Int ) -> Int { return ::square } fun square (x: Int ) = x * x fun main () { val func = operation() println(func(2 )) }
声明一个返回函数的高阶函数。(Int)-> Int 表示 square 函数的参数和返回类型。
声明与签名匹配的函数。
调用 operation 来获取赋值给变量的结果。这里 func 变成了由 operation 返回的 square。
调用 func,实际执行 square 函数。
Lambda 函数
Lambda 函数(“lambdas”)是创建临时函数的一种简单方法。 由于类型推断和隐式 it 变量,在许多情况下可以非常简洁地表示Lambda。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val upperCase1: (String) -> String = { str: String -> str.uppercase() } val upperCase2: (String) -> String = { str -> str.uppercase() } val upperCase3 = { str: String -> str.uppercase() } val upperCase5: (String) -> String = { it.uppercase() } val upperCase6: (String) -> String = String::uppercase println(upperCase1("hello" )) println(upperCase2("hello" )) println(upperCase3("hello" )) println(upperCase5("hello" )) println(upperCase6("hello" ))
一个光荣的 lambda,到处都是显式类型。Lambda 是大括号中的部分,它被赋给一个类型为 (String) -> String
(函数类型)的变量。
Lambda 内部的类型推断: lambda 参数的类型是从它所赋值的变量的类型推断出来的。
Lambda 之外的类型推断: 变量的类型是从 lambda 参数的类型和返回值推断出来的。
您不能同时进行这两项操作,编译器就没有机会以这种方式推断类型。
对于只有一个参数的 lambdas,您不必显式地为其命名。相反,您可以使用隐式 it 变量。当可以推断出它的类型时(通常是这种情况) ,这尤其有用。
如果您的 lambda 由单个函数调用组成,您可以使用函数指针( ::
)。
Infix Functions 中缀函数
具有单个参数的成员函数和扩展可以转换为中缀函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 fun main () { infix fun Int .times (str: String ) = str.repeat(this ) println(2 times "Bye " ) val pair = "Ferrari" to "Katrina" println(pair) infix fun String.onto (other: String ) = Pair(this , other) val myPair = "McLaren" onto "Lucas" println(myPair) val sophia = Person("Sophia" ) val claudia = Person("Claudia" ) sophia likes claudia } class Person (val name: String) { val likedPeople = mutableListOf<Person>() infix fun likes (other: Person ) { likedPeople.add(other) } }
在 Int 上定义中缀扩展函数。
调用中缀函数。
通过从标准库调用中缀函数来创建一个副。
下面是您自己创造性地调用的实现。
中缀表示法也适用于成员函数(方法)。
包含类成为第一个参数。
运算符函数
某些函数可以“升级”为运算符,允许它们使用相应的运算符符号进行调用。
1 2 3 4 5 6 operator fun Int .times (str: String ) = str.repeat(this ) println(2 * "Bye " ) operator fun String.get (range: IntRange ) = substring(range) val str = "Always forgive your enemies; nothing annoys them so much." println(str[0. .14 ])
这使用操作符修饰符将中缀函数从上面的步骤进一步提取出来。
times() 的操作符符号是 *
,因此可以使用 2 * "Bye "
调用函数。
运算符函数允许对字符串进行轻松的范围访问。
get()运算符启用了括号访问语法。
拓展函数和属性
Kotlin 允许您使用扩展机制向任何类添加新成员。也就是说,有两种类型的扩展: 扩展函数和扩展属性。它们看起来很像普通函数和属性,但有一个重要的区别: 您需要指定所扩展的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 data class Item (val name: String, val price: Float ) data class Order (val items: Collection<Item>)fun Order.maxPricedItemValue () : Float = this .items.maxByOrNull { it.price }?.price ?: 0F fun Order.maxPricedItemName () = this .items.maxByOrNull { it.price }?.name ?: "NO_PRODUCTS" val Order.commaDelimitedItemNames: String get () = items.map { it.name }.joinToString() fun main () { val order = Order(listOf(Item("Bread" , 25.0F ), Item("Wine" , 29.0F ), Item("Water" , 12.0F ))) println("Max priced item name: ${order.maxPricedItemName()} " ) println("Max priced item value: ${order.maxPricedItemValue()} " ) println("Items: ${order.commaDelimitedItemNames} " ) }
定义 Item 和 Order 的简单模型。 Order 可以包含 Item 对象的集合。
为 Order 类型添加扩展函数。
为 Order 类型添加扩展属性。
直接对 Order 实例调用扩展函数。
访问 Order 实例的扩展属性。