Kotlin笔记数据类型(一)
Kotlin笔记字符串(二)
Kotlin笔记运算符(三)
Kotlin笔记函数(四)
Kotlin笔记面向对象(五)
Kotlin笔记继承、抽象类、接口(六)
一个函数可以作为另一个函数的参数,或者返回值,那么这个函数就是“高阶函数”
Kotlin中每一个函数都有一个类型,称为“函数类型”,函数类型作为一种数据类型与数
据类型在使用场景没有区别
//定义计算长方形面积函数
//函数类型(Double, Double) -> Double
fun rectangleArea(width: Double, height: Double): Double { ①
return width * height
}
//定义计算三角形面积函数
//函数类型(Double, Double) -> Double
fun triangleArea(bottom: Double, height: Double) = 0.5 * bottom * height ②
fun sayHello() { //函数类型()->Unit ③
print("Hello, World")
}
fun main(args: Array<String>) {
val getArea: (Double, Double) -> Double = ::triangleArea ④
//调用函数
val area = getArea(50.0, 40.0) ⑤
print(area) //1000.0
}
函数类型可以声明的变量,那么函数类型变量能够接收什么的数据呢?即函数字面量如何
表示的问题,函数字面量可以有三种表示:
fun calculate(opr: Char): (Int, Int) -> Int {
//加法函数
fun add(a: Int, b: Int): Int {
return a + b
}
//减法函数
fun sub(a: Int, b: Int): Int {
return a - b
}
val result: (Int, Int) -> Int =
when (opr) {
'+' -> ::add ①
'-' -> ::sub ②
'*' -> {
//乘法匿名函数
fun(a: Int, b: Int): Int {
return (a * b)
}
}
else -> { a, b -> (a / b) } //除法Lambda表达式 ④
}
return result
}
fun main(args: Array<String>) {
val f1 = calculate('+') ⑤
println(f1(10, 5)) //调用f1变量 ⑥
val f2 = calculate('-')
println(f2(10, 5))
val f3 = calculate('*')
println(f3(10, 5))
val f4 = calculate('/')
println(f4(10, 5))
}
fun main(args: Array<String>) {
var funName=getFunWithType(2)
println(funName(1,3))
}
fun getFunWithType(type:Int):(Int,Int)->Int{
var functionType:(Int,Int)->Int
when(type){
1-> functionType=fun (a:Int,b:Int):Int=a+b
else -> functionType={a,b->a-b}
}
return functionType
}
fun main(args: Array<String>) {
var funName=getFunWithType(2)
println(operterFun(funName,4,5))
}
fun operterFun(funName:(Int,Int)->Int,a: Int,b: Int):Int{
return funName(a,b)
}
fun getFunWithType(type:Int):(Int,Int)->Int{
var functionType:(Int,Int)->Int
when(type){
1-> functionType=fun (a:Int,b:Int):Int=a+b
else -> functionType={a,b->a-b}
}
return functionType
}
{ 参数列表 -> Lambda体 }
Lambda表达式的参数列表与函数的参数列表形式类似,但是Lambda表达式参数列
表前后没有小括号。箭头符号将参数列表与Lambda体分隔开,Lambda表达式不需要声明
返回类型。Lambda表达式可以有返回值,如果没有return语句Lambda体的最后一个表
达式就是Lambda表达式的返回值,如果有return语句返回值是return语句后面的表达
式。
fun main(args: Array<String>) {
var funLa={a:Int,b:Int-> a+b}
println(funLa(2,4))
}
{a:Int,b:Int-> a+b} 可以简化成
{ a, b -> a + b }
尾随Lambda 如果一个函数的最后一个参数是Lambda表达式,那么这个Lambda表达
式可以放在函数括号之后。
fun main(args: Array<String>) {
//正常调用
// operterFun(2,3,{a,b->a+b})
//尾随写法
operterFun(2,3){a,b->
a+b
}
}
fun operterFun(a: Int,b: Int,funName:(Int,Int)->Int):Int{
return funName(a,b)
}
如果Lambda表达式的参数只有一个,并且能够根据上下文环境推导出它的数据类
型,那么这个参数声明可以省略,在Lambda体中使用隐式参数it替代Lambda表达
式的参数
fun main(args: Array<String>) {
operterLa("zyb"){ println(it)}
}
fun operterLa(name:String,funName: (String)->Unit){
funName(name)
}
Lambda表达式体中也可以使用return语句,它会使程序跳出Lambda表达式体
fun main(args: Array<String>) {
println(sum(1,2,3,10,3)) //9
val add = label@ {
val a = 1
val b = 2
return@label 10
a + b
}
//调用Lambda表达式add
println(add()) //10
}
//累加求和函数
fun sum(vararg num: Int): Int {
var total = 0
num.forEach {
// if (it == 10) return -1 //返回最近的函数 ②
if (it == 10) return@forEach//返回Lambda表达式函数 ③
total += it
}
return total
}
闭包(closure)是一种特殊的函数,它可以访问函数体之外的变量,这个变量和函数一
同存在,即使已经离开了它的原始作用域也不例外。这种特殊函数一般是局部函数、匿名
函数或Lambda表达式
fun makeArray(): (Int) -> Int { ①
var ary = 0 ②
//局部函数捕获变量
fun add(element: Int): Int { ③
ary += element ④
return ary ⑤
}
return ::add ⑥
}
fun main(args: Array<String>) {
val f1 = makeArray() ⑦
println("---f1---")
println(f1(10))//累加ary变量,输出结果是10
println(f1(20))//累加ary变量,输出结果是30
}
在高阶函数中参数如果是函数类型,则可以接收Lambda表达式,而Lambda表达式在编译
时被编译称为一个匿名类,每次调用函数时都会创建一个对象,如果这种被函数反复调用
则创建很多对象,会带来运行时额外开销。为了解决次问题,在Kotlin中可以将这种函数
声明为内联函数。
提示 内联函数在编译时不会生成函数调用代码,而是用函数体中实际代码替换每次
调用函数
使用关键字 inline
inline fun calculatePrint(funN: (Int, Int) -> Int) { ①
println("${funN(10, 5)}")
}
fun main(args: Array<String>) {
calculatePrint { a, b -> a + b } ②
calculatePrint { a, b -> a - b } ③
}
在Kotlin中一个函数参数被声明为非空类型时,也可以接收可空类型的参数,但是如果实
际参数如果真的为空,可能会导致比较严重的问题。因此需要在参数传递之前判断可空参
数是否为非空
fun main(args: Array<String>) {
sayNameLength(null)
}
fun sayNameLength(name:String?){
// if (name!=null){
// println(name.length)
// }
name?.let {println(it.length) }
}
有时候需要对一个对象设置多个属性,或调用多个函数时,可以使用with或apply函数。
与let函数类似Kotlin中所有对象都可以使用这两个函数
with 返回表达式的最后一句,apply 返回的是一个对象
fun main(args: Array<String>) {
//sayNameLength(null)
var name=StringBuilder(0)
var stringBuilder2=name.apply{
append("hello")
append(" ")
append("world")
}
var stringBuilder3= with(name){
this.append("\n")
this.append("My name is ")
this.append("zyb")
"我是with"
}
println(name)
println(stringBuilder2)
println(stringBuilder3)
## hello world
## My name is zyb
## hello world
## My name is zyb
## 我是with
}