kotlin 函數詳解

kotlin 函數詳解

構造方法

在Kotlin中,一個類可以有一個primary構造方法以及一個或多個Secondary構造方法,primary構造方法是類頭(class header)的一部分,它位於類名後面,可以擁有若干參數,如果primary構造方法沒有任何註解或是可見性關鍵字修飾,那麼construction關鍵字可省略。

class Myclass constructor(user: String) {
    private val name: String = user.toLowerCase()

    init {
        println(user)
    }
}

fun main(args: Array<String>) {
    val myClass = Myclass("zhangsan")
}

次構造方法

class Person constructor(username: String) {
    private var username: String
    private var age: Int
    private var sex: String

    init {
        this.age = 20
        this.sex = "男"
        this.username = "張三"
    }

    constructor(username: String, age: Int) : this(username) { //次構造方法,this傳遞主構造方法
        this.username = username
        this.age = age
        this.sex = "女"
    }

    constructor(username: String, age: Int, sex: String) : this(username, age) {
        this.username = username
        this.age = age
        this.sex = sex
    }

    fun printInfo() {
        println("username:${this.username},age:${this.age},sex:${this.sex}")
    }
}

fun main(args: Array<String>) {
    val person = Person("李四")
    val person2 = Person("李四", 70)
    val person3 = Person("李四", 20, "男")
    println(person.printInfo())
    println(person2.printInfo())
    println(person3.printInfo())
}

var,val 在構造方法中定義參數:

class Student(private val name: String,private val age: Int) {
//加了var val就是成員變量,刪掉就會報錯,數據類中都的參數會加上var或者val
    fun printInfo() {
        println("name:$name,age:$age")
    }
}

如果構造方法擁有註解或是可見修飾符,那麼constructor關鍵字是不能省略的,並且位於修飾符後面

class Student2 private constructor(username: String) {}

默認參數(default arguments)

在jvm上,如果類的primary構造方法的所有參數都擁有默認值,那麼kotlin編譯器就會成爲這個類生成,一個不帶參數的構造方法,這個不帶參數的構造方法會使用這些參數的默認值,這樣做的目的在於可以跟Spring等框架更好的集成

class Student3(val username: String = "zhangsan") {}

fun main() {
    val student = Student3()//沒有傳遞任何參數,默認參數就是無參構造函數
    println(student.username) //zhangsan
}
fun test(a:Int=0,b:Int=2)= println(a-b)
fun main(args: Array<String>) {
    test(2) //a=2,默認傳遞第一個參數
    test(b=3)//b=3,具名參數,具體賦值給哪一個參數
    test(2,3)
}

對於重寫的方法來說,子類所擁有的重寫方法會使用與父類相同的默認參數值。在重寫一個擁有默認參數值的方法時,方法簽名中必須要將默認參數值省略掉。如下例子:

open class A{
    open fun method (a:Int,b:Int=3)=a+b
}
class B:A(){
    override fun method(a: Int, b: Int=5)=a+b //會報錯。當前b的值是3,不能去指定默認值
    override fun method(a: Int, b: Int)=a+b //正確
}
fun main(args: Array<String>) {
    println(A().method(1)) //6
    println(B().method(6)) //11
}

如果一個默認參數位於其他無默認值的參數前面,那麼默認值只能通過在調用函數時使用具名函數的方式來使用,如下例子:

fun test2(a:Int =1,b:Int)= println(a-b)

fun main(args: Array<String>) {
    test2(b=3)//具名參數
    test2(3)// 此時傳給的a=3,會報錯,因爲當前a=1了。
}

lamba 表達式的函數

如果函數的最後一個參數是lambda表達式,而且在調用時是位於圓括號之外。那麼就可以不指定lambda表達式的具名參數名。如下例子:

fun test3(a: Int=1,b: Int=2,compute:(x:Int,y:Int)->Unit){
    compute(a,b)
}
fun main(args: Array<String>) {
    test3(2,3, {a,b -> println(a-b)}) //-1
    test3(2,3) {a,b -> println(a-b)} //-1
    test3(2){a,b -> println(a-b)} //0
    test3{a,b -> println(a-b)} //0
    //以上表示都正確的
}

具名參數

在調用函數時,函數參數可以是具名的。當一個函數有大量參數或是一些參數擁有默認值,這種調用方式是比較方便的。如下例子:

fun test4(a: Int,b: Int=2,c: Int=1,d: Int)= println(a+b+c+d)
fun main(args: Array<String>) {
    test4(a=2,d = 5)
    test4(1,2,3,4)
}

可變參數 vararg

一個方法中,只允許一個參數爲vararg,通常作爲最後一個參數,如果vararg不是最後一個參數,那麼其後的參數就需要通過具名參數形式進行傳遞;如果其後的參數是函數類型,那麼還可以通過在圓括號外傳遞lambda表達式來實現。如下例子:

fun  test5(vararg strings:String){
    println(strings.javaClass) //strings 的java類型是數組類型
    strings.forEach { println(it) }
}
fun main(args: Array<String>) {
    test5("a","sf","sdf")
    test5(strings = arrayOf("a","c","f")) //此處是錯誤的
    //要加一個*號,分散運算符
    test5(strings = *arrayOf("a","c","f"))
    val arrays= arrayOf("a","b")
    test5(*arrays)
}

內聯函數(inline function)

inline fun myCalculate(a:Int,b:Int)=a+b
fun main(args: Array<String>) {
    println(myCalculate(1,2))
}

匿名函數 必須要放在圓括號裏面實現

fun(x: Int, y: Int) = x + y  //complier error必須要有一個方法名

fun main(args: Array<String>) {
    fun(x: Int, y: Int) = x + y
    fun(x: Int, y: Int): Int {
        return x + y
    }

    val strings = arrayOf("hello", "world")
    strings.filter(fun(item): Boolean = item.length > 3).forEach(fun(item) {
        println(item)
    })
}

注意:

  • 在調用函數時,如果同時使用了位置參數與具名參數,那麼所有的位置參數都必須要位於第一個具名參數之前。比如說,foo(1,x=2)是允許的,foo(x=2,1)是不允許的。
  • 在kotlin中調用java方法時不能使用具名參數語法,因爲java字節碼並不總是會保留方法參數名信息。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章