Kotlin知識概括(二) —— 讓函數更好調用

函數參數之惑

        當一個函數擁有多個參數,且存在多個相同類型參數緊挨着的狀況時,每每不太清楚傳入參數的位置是否正確,且嚴重影響函數的可讀性。須要調用者跳轉到函數對應的地方,對參數和函數定義中的參數列表進行匹對。這將對函數調用者形成很大的麻煩和困擾。android

fun <T> joinToString(collection: Collection<T>,
                     separator:String,
                     prefix:String,
                     postfix:String):String{
    val result = StringBuilder(prefix)
    for ((index,element) in collection.withIndex()){
        if (index > 0)
            result.append(separator)
        result.append(element)
    }
    result.append(postfix)
    return result.toString()
}
複製代碼

        針對這種狀況,或許能夠依靠IDE進行優化。如:Idea早已對此進行了優化,在對函數填寫參數時,會將參數對應位置的參數名稱進行提示。bash

命名參數

        Kotlin在語法層上對該狀況進行優化,當調用一個Kotlin定義的函數時,能夠顯示標明參數的名稱。這種參數叫命名參數。app

        當指明一個參數的名稱後,避免混淆,其餘參數都要標明名稱。(既然顯式的標明名稱,也就不須要按本來參數定義的順序傳入參數)函數

joinToString(array,prefix = "(",separator = ",", postfix = "]")
複製代碼

注意:

  • 既然顯示的標明瞭參數名,也就意味着當參數名或方法名進行改變時,其顯式標明的參數名或方法名也須要進行改變。這時可使用Idea的Rename進行修改。(先選中方法名或參數名 -> Refactor -> Rename)
  • 當調用Java定義的函數時,不能採用命名參數,由於Java8以前不能把參數名存在,class文件中。而Kotlin須要與Java6兼容。因此,編譯器不能識別出函數參數的名稱。

函數重載之禍

        在Java中,支持對函數進行重載。這就形成多個相同名稱的函數,且其參數間只有細微的差異。當調用省略部分參數的函數時,可能不清楚到底調用的是哪個函數。(例如:Thread類擁有8個構造函數)post

默認參數

        而Kotlin只須要指定參數的默認值,就能夠有效避免建立多個重載函數。這種帶有默認值的函數參數叫作默認參數。再配合命名參數進行使用時,能夠很方便的對指定參數進行賦值,從而實現重載。優化

fun <T> joinToString(collection: Collection<T>,
                          separator:String = ",",
                          prefix:String = "",
                          postfix:String = ""):String
複製代碼

調用時只須要傳入具體的集合對象,函數會使用默認參數的默認值對其進行運算。ui

固然,按參數定義的順序,傳入對應的參數也徹底沒有問題。spa

val string = joinToString(array)
//像之前傳遞前綴,分割符和後綴也沒有問題
val string = joinToString(array,"(",",")
val string = joinToString(array,"(",",", "]")
//配合命名參數食用,效果更佳
val string = joinToString(array,separator = ";")
複製代碼

@JvmOverloads 提升Kotlin與Java的交互性

        Java 中沒有默認參數的概念,當從Java中調用Kotlin的函數時,必須顯示地傳遞全部參數值。爲了讓Java調用者能調用該方法的重載函數,能夠用@JvmOverloads註解它。在編譯時,編譯器會從最後一個參數開始逐個省略,生成Java的重載函數。.net

局部函數

        程序猿都認爲方法越小越好,相比縱向冗長的代碼片斷,將其按照職責切分紅功能單一的小的局部方法,最後組織起來調用是最好的。但不少時候分解出來的小方法之間並無什麼明確的關係,最後以一個包含許多小方法的類了結。3d

        Kotlin中支持局部函數,所謂局部函數就是在方法中聲明方法,內部方法能夠獲取到外部函數的參數和局部變量。能夠將各個小方法定義爲局部方法,即提供所需的簡潔結構也無須額外的語法開銷。

data class Person(val age:String?,val name:String?)

fun daqi(person: Person){
    if (person.age == null){
        throw IllegalArgumentException()
    }
    if (person.name == null){
        throw IllegalArgumentException()
    }
    //正常操做

}
複製代碼

轉換爲局部函數:

fun daqi(person: Person){
    //須要在頂層定義,否則函數未定義沒法使用
    fun personFileIsEmpty(value:String?,fileName:String){
        if (value == null){
            throw IllegalArgumentException("$fileName is null")
        }
    }
    
    personFileIsEmpty(person.age,"age")
    personFileIsEmpty(person.name,"name")
    
    //正常操做
}
複製代碼

        局部函數的缺點是:局部函數的不能聲明爲內聯,而且擁有局部函數的的函數也不能聲明爲內聯。暫時沒有任何辦法避免這種函數的調用成本。

參考資料:

android Kotlin系列:

Kotlin知識概括(一) —— 基礎語法

Kotlin知識概括(二) —— 讓函數更好調用

Kotlin知識概括(三) —— 頂層成員與擴展

Kotlin知識概括(四) —— 接口和類

Kotlin知識概括(五) —— Lambda

Kotlin知識概括(六) —— 類型系統

Kotlin知識概括(七) —— 集合

Kotlin知識概括(八) —— 序列

Kotlin知識概括(九) —— 約定

Kotlin知識概括(十) —— 委託

Kotlin知識概括(十一) —— 高階函數

Kotlin知識概括(十二) —— 泛型

Kotlin知識概括(十三) —— 註解

Kotlin知識概括(十四) —— 反射

相關文章
相關標籤/搜索