Kotlin开发安卓APP笔记-函数和lambda表达式(2)

接着上一篇Kotlin开发安卓APP笔记-函数和lambda表达式(2)继续学习

可变参数数量Varargs

使用“vararg”关键字修饰参数,即可定义为可变数量参数(一般是最后一个参数):

    fun asList(vararg ts: Any): List {
        val result = ArrayList()
        for (t in ts) {
            result.add(t)
        }
        return result
    }

等同Java版:

    List<Object> asList(Object... ts){
        List<Object> result=new ArrayList<>();
        for (Object t:ts) {
            result.add(t);
        }
        return result;
    }

该函数可以接收不定个数参数:

val list = asList(1, 2, 3) 
val list2 = asList("bestmk.cn","猫客技术论坛") 

在函数内部,被“vararg”修饰的参数实际上是一个数组(Array< out T>)。
一个函数,只能有一个参数可以使用“vararg”关键字修饰,一般放在最后一个参数。若不是最后一个参数,在使用时,其他的参数可以使用命名参数(Named Arguments)方式;或者函数有一个功能类型参数,可以在函数的后面定义一个Lambda表达式实现。

// vararg参数不是最后一个参数情况  
fun asMultipleList(vararg ts: Int, multiple: Int): List {  
val resultL = ArrayList()  
    for(data in ts) {  
        resultL.add(data * multiple)  
     }  
return resultL  
}  
//  
var multiList = asMultipleList(1, 2, 3, multiple=2)  
println(multiList)  

//后面更有功能类型参数  
fun showInfo(vararg infos: String, show: (info: String) -> Unit) {  
for(info in infos) {  
        show(info)  
    }  
}  
//  
showInfo("info1", "info2") {  
println(it)  
}  

调用一个“vararg”函数时,可以一个一个值使用,如“asList(1, 2, 3)”;也可以直接使用一个存在的数组数据,使用“*”关键字:

val a = arrayOf(1, 2, 3)  
val list = asList(-1, 0, *a, 4)  

中缀表示法Infix和扩展函数

很多教程都是将Infix放在扩展函数前面,不合理,即使会Java也不方便理解,所以先学习扩展函数
所谓扩展函数就是扩展类的函数, 即 Extension Function , 可以在已有类中添加新的方法, 比继承更加简洁和优雅。在Kotlin中,允许对类进行扩展,不需要继承或使用 Decorator 模式,通过一种特殊形式的声明,来实现具体实现某一具体功能。扩展函数是静态解析的,并未对原类增添函数或者属性,也就是说对其本身没有丝毫影响。
扩展函数定义方式:

fun receiverType.functionName(params){
    body
}

receiverType:表示函数的接收者,也就是函数扩展的对象
functionName:扩展函数的名称
params:扩展函数的参数,可以为NULL

扩展函数并没有对原类做修改,而是为被扩展类的对象添加新的函数。

    fun Int.add(vararg nums:Int):Int{
        var result:Int=0
        for (num in nums)result=result+num
        return result
    }

为Int声明了一个扩展函数add,用来计算多个数相加的结果,学习一定要灵活,将学到的东西灵活运用起来
使用方式:add(1,2,3) 或者 1.add(1)
在实际开发时,如果对一个类某一功能并不通用,只有某些特殊场景使用时,可以使用扩展函数,从而显得灵活多变。
之前说过,扩展函数是静态解析的,也就是,它并不是接收者类型的虚拟成员,意味着调用扩展函数时,调用扩展函数时,具体被调用的的是哪一个函数,由调用函数的的对象表达式来决定的,而不是动态的类型决定的。比如先声明了两个类Person和Teacher,其中teacher继承于Person,
在测试实例中,分别对Person和Teacher声明了扩展函数doFly(),又声明了fly()方法,其参数是一个Person对象,在其方法体内,调用了Person的扩展函数。现在测试实例中,创建了一个Teacher对象teacher,调用fly()方法并将teacher过去,实际上会调用哪个扩展函数呢?

open class Person {
}

class Teacher: Person() {
}

// 测试实例
fun Person.doFly() {
    println("Person do fly")
}

fun Teacher.doFly() {
    println("Teacher do fly")
}

fun fly(person: Person) {
    person.doFly()
}

fun main(args: Array) {

    var teacher: Teacher = Teacher()

    fly(teacher)
}

// Log
Person do fly

从Log打印中,可以清晰的看到的是,fly(teacher)调用的是Person的扩展函数。因为调用哪个函数, 仅仅是由参数person声明的类型决定, 这里参数person的类型为Person类.
现在我们了解了扩展函数,再来看中缀表达式infix
使用Infix需要满足以下三个条件:
1,它们是成员函数或扩展函数
2,他们有一个单一的参数
3,他们用infix关键字标记
例如刚刚写的add函数例子用中缀表达式就可以写为:1 add 2,增加了代码的美观性

功能范围

kotlin可以不需要像Java一样创建一个类来保存函数,直接在顶层写函数,除顶层函数之外,Kotlin函数也可以声明为本地函数,作为成员函数和扩展函数。
Kotlin支持本地函数,即另一个函数内的函数:

fun dfs(graph: Graph) {
    fun dfs(current: Vertex, visited: Set) {
        if (!visited.add(current)) return
        for (v in current.neighbors)
            dfs(v, visited)
    }

    dfs(graph.vertices[0], HashSet())
}

本地函数可以访问外部函数的局部变量(即闭包),所以在上面的例子中,visited可以是局部变量:

fun dfs(graph: Graph) {
    val visited = HashSet()
    fun dfs(current: Vertex) {
        if (!visited.add(current)) return
        for (v in current.neighbors)
            dfs(v)
    }

    dfs(graph.vertices[0])
}

成员函数是在类或对象内定义的函数:

class Sample() {
    fun foo() { print("Foo") }
}

成员函数用点符号调用:Sample().foo()

通用函数

函数可以具有在函数名称前使用尖括号指定的泛型参数:

fun <T> singletonList(item: T): List<T> {
    // ...
}

今天先学习到这里,我去吃饭先,明天学习内联函数,高阶函数和lambda表达式,尾递归函数

你可能感兴趣的:(安卓,Kotlin,android,kotlin,函数)