Kotlin-21.函式(Functions)
阿新 • • 發佈:2019-02-01
1.函式定義和呼叫
相比java, kotlin函式定義/宣告非常方便簡單 1.函式宣告定義/宣告(Function Declarations): //Unit型別表示沒有返回值 fun demo(): Unit { ... // return Unit 或 return 是可選的 } //可以省略Unit fun demo() { ... // return Unit 或 return 是可選的 } 2.單表示式函式定義/宣告: //當函式返回單個表示式時,可省略花括號{},並用等號指定函式程式碼體: fun double(x: Int): Int = x * 2 //當返回型別可由編譯器推斷出時,可省略返回型別: fun double(x: Int) = x * 2
1.傳統呼叫
呼叫普通函式:
demo()
呼叫成員函式:
class Sample() {
fun foo() { print("Foo") }
}
Sample().foo()
2.中綴呼叫(Infix notation)
中綴呼叫就是使用[中綴標記]呼叫函式,非常類似於加減乘除(+ - * /) 必須滿足以下條件: 函式作為類的成員函式 或 擴充套件函式 函式必須且只有一個引數 函式字首有 infix 標記 // 擴充套件函式-中綴表示/標記 infix fun Int.add(i: Int): Int{ return this + i } // 成員函式-中綴表示/標記 class MyInt(var a: Int){ infix fun add(i: Int): Int{ return a + i } } fun main(args: Array<String>) { println(2 add 3) //中綴呼叫,輸出5 println(2.add(3)) //傳統呼叫,輸出5 val i = MyInt(2) println(i add 3) //中綴呼叫,輸出5 println(i.add(3)) //傳統呼叫,輸出5 }
2.函式引數
函式引數用Pascal表示法定義(即name: type),引數用逗號分隔,引數必須要有顯式型別:
fun myFun(p1: Int, p2: Int) {
}
1.預設引數(Default Arguments)
函式引數可以有預設值,當函式呼叫沒有引數時,就使用預設值: fun myFun(p1: Int = 1, p2: Int = 2) { } 子類覆蓋方法與基類(父類)方法預設引數值相同,父類有預設引數,子類不能寫預設引數: open class A { open fun foo(i: Int = 10) { } } class B : A() { // 父類已有,子類不能有預設引數值 override fun foo(i: Int) { } }
2.命名引數(Named Arguments)
當函式有大量引數時呼叫會非常不方便:
fun myFun(a: String = "lioil",
b: Boolean = true,
c: Int = 1,
d: Char = 'w') {
}
//修改引數c,其它引數保持預設,雖然有預設引數,但是依然麻煩!!!
myFun("lioil",true,2)
//此時可用命名引數(Named Arguments)簡化:
myFun(c = 2)
3.引數個數可變(vararg)
函式引數用vararg標記,可使引數個數可變:
fun <T> asList(vararg ts: T){
for (t in ts) //引數ts相當於陣列Array <out T>
print("$t,")
}
fun main(args: Array<String>) {
asList(1,2,3) //輸出1,2,3,
//傳遞陣列,新增伸展(spread)操作符*
val a = arrayOf(1, 2, 3)
asList(0, *a, 4) //輸出0,1,2,3,4,
}
如果vararg標記的引數不是最後一個引數,需要用[命名引數]傳遞其之後的引數:
fun <T> asList(vararg ts: T, name: String){
for (t in ts)
print("$t,")
print(name)
}
fun main(args: Array<String>) {
asList(1,2,3,name="lioil.win")//輸出1,2,3,lioil.win
}
3.函式種類
Kotlin函式可在檔案頂層定義/宣告,無需像Java、C#、Scala那樣在一個類中定義一個函式,
所以說函式是kotlin世界的第一公民!
此外,Kotlin函式也可在區域性作用域定義,作為函式內部的函式,類的成員函式或擴充套件函式!
1.本地/區域性函式(Local Functions)-函式內部的函式
Kotlin支援區域性函式,即一個函式在另一個函式內部:
fun main(args: Array<String>) {
val name = "lioil.win"
fun myFun() {
//區域性函式可訪問外部函式(即閉包)的區域性變數name
println(name)
}
myFun() //輸出 lioil.win
}
2.成員函式(Member Functions)是在類或物件內部定義的函式
class Sample() {
fun foo() { print("Foo") }
}
//成員函式呼叫
Sample().foo()
3.泛型函式(Generic Functions),在函式名前使用尖括號<>指定泛型
fun <T> singletonList(item: T): List<T> {
}
4.尾遞迴函式(Tail recursive functions)
Kotlin支援尾遞迴(tail recursion)函式: 使用尾遞迴函式替迴圈程式碼,不會有堆疊溢位的風險!
使用tailrec修飾符標記函式,編譯器會把尾遞迴優化成高效迴圈程式碼!
使用tailrec修飾符的條件:
遞迴呼叫必須是函式體的最後一個操作(即保證是尾遞迴)
不能用在 try/catch/finally 塊中
目前尾部遞迴只在 JVM 後端中支援
//尾遞迴程式碼
tailrec fun findFixPoint(x: Double = 1.0): Double
= if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))
//最終被編譯器優化成迴圈程式碼
private fun findFixPoint(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if (x == y) return y
x = y
}
}
5.行內函數(Inline Functions)、擴充套件函式(Extension Functions)、
高階函式(Higher-Order Functions)和Lambda表示式等在其它章節中...