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知识概括(十四) —— 反射

相关文章
相关标签/搜索