一、函数的特性语法
- 函数的几种声明形式
//普通声明形式
fun sayHello(str: String){
print(str)
}
//允许参数有默认值,可用于方法重载
fun printName(str: String = "Irving"){
print(str)
}
//函数体只有一行代码时
fun printlnName(str: String) = println(str)
二、函数嵌套
函数嵌套会降低代码的可读性,只会在某些场景下时候运用:
- 某些条件下触发递归的函数
- 不希望被外部函数访问到的函数
fun test(){
fun sayHello(count: Int = 10){
if (count > 0){
println("sayHello!!")
sayHello(count - 1)
}
}
sayHello()
}
三、扩展函数和扩展参数
对三方
SDK
和无法控制的类,使用
Kotlin
可以很方便的对其进行扩展,添加成员方法和成员属性。扩展函数是通过装饰者模式,编译时将扩展函数编译为
Java
中的静态方法,因此是静态解析,不具备运行时的多态特性。
// 给String类添加扩展函数
fun String.isIrving(): Boolean = this == "Irving"
// 给String类添加扩展属性
var String.irving: String
get() = this
set(value) {
print(value)
}
调用时:
fun main(args: Array<String>) {
//调用扩展函数
print("Irving".isIrving())
val a = "test"
//设置扩展属性的值
a.irving = "Irving"
print(a)
}
四、Lambda闭包
-
中的Kotlin
函数有以下特点Lambda
fun testLambda(){
//一般写法
val thread01 = Thread({ -> println() })
//如果Lambda表达式没有参数,可以省略 ->
val thread02 = Thread({ println() })
//如果Lambda表达式是函数的最后一个参数,可以将Lambda表达式放在小括号的外面
val thread03 = Thread(){ println() }
//如果该函数只有一个参数且该参数为Lambda表达式,可以省略小括号
val thread04 = Thread {println()}
}
- 声明闭包
val sayMessage = {message: String ->
println(message)
}
fun main(args: Array<String>) {
sayMessage("Irving")
}
注意使用
Kotlin
声明闭包时最多只能含有22个参数。需要超过22个参数时需要自己手动添加对应的接口。
五、高阶函数
高阶:函数(
Lambda
)的参数是函数(
Lambda
)
//高阶函数, 将函数声明作为参数
fun test(right: Boolean, block: () -> Unit){
if (right) block()
}
//调用高阶函数时,第二个参数传入一个Lambda函数
fun main(args: Array<String>){
test(true){
println("Hello World")
}
}
调用高阶函数时必须传入函数声明,不能通过
Any.fun()
传入,因为这样是传入方法的返回值,
Kotlin
提供了
Any::fun
这种方式传入函数声明。
//高阶函数, 将函数声明作为参数
fun test(right: Boolean, block: () -> Unit){
if (right) block()
}
//调用高阶函数时,第二个参数传入一个函数声明
fun main(args: Array<String>){
//创建一个Runnable对象
val runnable = Runnable{
println("Hello World")
}
//创建一个没有返回值的函数对象
val function: () -> Unit
//将Runnable对象的run方法传递给function函数对象
function = runnable::run
//上面两步可以简化为:
// val function = runnable::run
//将function函数声明作为参数传递给高阶函数
test(true, function)
}
注意:
Kotlin
中
Lambda
表达式会被编译为匿名对象,如果代码中有大量重复的
Lambda
表达式,就会生成很多无用的临时对象,这个时候可以使用
inline
关键字修饰高阶函数,这样当方法在编译时就会拆解方法的调用为语句的调用,从而减少创建不必要的对象。但是过度使用
inline
关键字会加大编译器的负担,使代码块变得很庞大,查找问题变得更加困难,所以一般
inline
关键字只用于修饰高阶函数。
//使用inline关键字修饰高阶函数, 将函数声明作为参数
inline fun test(right: Boolean, block: () -> Unit){
if (right) block()
}