高階函數的定義
高階函數和Lambda的關系是密不可分的。在之前的文章中,我們熟悉了Lambda編程的基礎知識,并且掌握了一些與集合相關的函數式API的用法,如map
、filter
函數等。另外,我們也了解了Kotlin的標準函數,如run
、apply
函數等。
這些函數有一個共同的特點:它們都會要求傳入一個Lambda表達式作為參數。像這種接收Lambda參數的函數就可以稱為具有函數式編程風格的API,而如果你想要定義自己的函數式API,那就得借助高階函數來實現了。
所以高階函數的定義:如果一個函數接收另一個函數作為參數,或者返回值的類型是另一個函數,那么該函數就稱為高階函數。
這個定義可能有點不太好理解,一個函數怎么能接收另一個函數作為參數呢?這就涉及另外一個概念了:函數類型。我們知道,編程語言中有整型、布爾型等字段類型,而Kotlin又增加了一個函數類型的概念。如果我們將這種函數類型添加到一個函數的參數聲明或者返回值聲明當中,那么這就是一個高階函數了。
定義一個函數類型
不同于定義一個普通的字段類型,函數類型的語法規則是有點特殊的,基本規則如下:
(String, Int) -> Unit
既然是定義一個函數類型,那么最關鍵的就是要聲明該函數接收什么參數,以及它的返回值是什么。因此,->
左邊的部分就是用來聲明該函數接收什么參數的,多個參數之間使用逗號隔開,如果不接收任何參數,寫一對空括號就可以了。而->
右邊的部分用于聲明該函數的返回值是什么類型,如果沒有返回值就使用Unit
,它大致相當于Java中的void
。
現在將上述函數類型添加到某個函數的參數聲明或者返回值聲明上,那么這個函數就是一個高階函數了,如下所示:
fun example(funExample: (String, Int) -> Unit) {funExample("你好", 111)
}
如果是有返回值的,代碼示例:
fun example(name: String, age: Int, getStudent: (String, Int) -> Student): Student {return getStudent(name, age)
}
這里我們定義了一個getStudent的函數用來返回Student對象,那么我們就可以定義一個方法,代碼如下:
fun gStudent(name:String,age: Int):Student{val student=Student("001",1)student.name=namestudent.age=agereturn student
}
然后調用:
val student= example("我的",12,::gStudent)println("name=${student.name}------age=${student.age}")
打印結果:
你會發現,當我們需要返回值時,我們需要定義個方法來讓高階函數調用,這樣是不是太麻煩了,Kotlin也考慮到了這一點,我們可以通過Lambda表達式、匿名函數、成員引用等。其中,Lambda表達式是最常見也是最普遍的高階函數調用方式。
我們仍以上面的高階函數為例,改成Lambda表達式,示例如下:
val student2 = example("張三", 12,) { name,age ->val student =Student("",2)student.name=namestudent.age=agestudent}println("name=${student2.name}------age=${student2.age}")
這樣我們就不需要單獨再去定義個函數來調用,我們可以直接在Lambda表達式中對參數進行操作,從而得到我們想要的數據