一、函數的特性文法
- 函數的幾種聲明形式
//普通聲明形式
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()
}