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

来源:互联网 发布:windows media center 编辑:程序博客网 时间:2024/06/07 13:05

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

可变参数数量Varargs

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

    fun asList(vararg ts: Any): List<Any> {        val result = ArrayList<Any>()        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<Int> {  val resultL = ArrayList<Int>()      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<String>) {    var teacher: Teacher = Teacher()    fly(teacher)}// LogPerson 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<Vertex>) {        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<Vertex>()    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表达式,尾递归函数

阅读全文
0 0
原创粉丝点击