Android 开发上手 Kotlin 函数学习

文章目录

  • 基础函数
    • 函数声明
    • 函数用法
    • 函数传参
      • 默认参数
      • 可变数量的参数
  • 局部函数
  • lambda 表达式
  • 匿名函数
  • 高阶函数
    • let 函数
    • with 函数
    • run 函数
    • apply 函数
    • also 函数
  • 内联函数
  • 扩展函数
    • 扩展函数写法
  • 总结

基础函数

函数声明

Kotlin 中的函数使用 fun 关键字声明:

fun double(x: Int): Int {
    return 2 * x
}

函数用法

调用函数使用传统的方法:

val result = double(2)

函数传参

函数参数使用 Pascal 表示法定义,即 name: type
参数用逗号隔开。每个参数必须有显式类型:

fun powerOf(number: Int, exponent: Int) { /*……*/ }

默认参数

函数参数可以有默认值,当省略相应的参数时使用默认值。
与其他语言相比,这可以减少重载方法数量:

// 声明
fun read(b: String, off: Int = 0, len: Int = b.size) { /*……*/ }

// 可通过下面三种方式调用
read("hello")
read("hello", 10)
read("hello", 10, 1024)

默认值通过类型后面的=及给出的值来定义。

可变数量的参数

函数的参数(通常是最后一个)可以用 vararg 修饰符标记:

// 声明
fun <T> asList(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts) // ts is an Array
        result.add(t)
    return result
}

// 调用
val list = asList(1, 2, 3)

局部函数

Kotlin 支持局部函数,即一个函数在另一个函数内部

局部函数可以访问外部函数(即闭包)的局部变量,
所以在上例中,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])
}

lambda 表达式

匿名函数

上面提供的 lambda 表达式语法缺少的一个东西是指定函数的返回类型的能力。在大多数情况下,这是不必要的。因为返回类型可以自动推断出来。然而,如果确实需要显式指定,可以使用另一种语法: 匿名函数 。

Lambda 表达式的完整语法形式如下:

val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

高阶函数

高阶函数是将函数用作参数或返回值的函数。

示例来源:
https://juejin.im/post/5b198c675188257d7a49b3ec

// 源代码
fun test(a : Int , b : Int) : Int{
    return a + b
}

fun sum(num1 : Int , num2 : Int) : Int{
    return num1 + num2
}

// 调用
test(10,sum(3,5)) // 结果为:18

let 函数

在函数块内可以通过 it 指代该对象。
常见写法 let 函数处理需要针对一个可null的对象统一做判空处理

mVideoPlayer?.setVideoView(activity.course_video_view)
mVideoPlayer?.setControllerView(activity.course_video_controller_view)
mVideoPlayer?.setCurtainView(activity.course_video_curtain_view)

// 上面的写法可以使用 it 指代该对象改为下面的写法
mVideoPlayer?.let {
   it.setVideoView(activity.course_video_view)
   it.setControllerView(activity.course_video_controller_view)
   it.setCurtainView(activity.course_video_curtain_view)
}

with 函数

它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式

适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可
经常用于Android RecyclerView onBinderViewHolder中,数据model的属性映射到UI

override fun onBindViewHolder(holder: ViewHolder, position: Int){
    val item = getItem(position)?: return
    with(item){
        holder.nameView.text = "姓名:$name"
        holder.ageView.text = "年龄:$age"
    }
}

run 函数

实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式 ,适用于let, with函数任何场景。

run函数弥补了let函数在函数体内必须使用it参数替代对象,也可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中也可以像let函数一样做判空处理

override fun onBindViewHolder(holder: ViewHolder, position: Int){
    val item = getItem(position)?: return
    item?.run {
        holder.nameView.text = "姓名:$name"
        holder.ageView.text = "年龄:$age"
    }
}

apply 函数

从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭包形式返回最后一行代码的值,而apply函数返回的是传入对象的本身

apply一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值。或者动态inflate出一个XMLView的时候需要给View绑定数据也会用到,这种情景非常常见

// 返回对象本身
val person = Person("Tom", 100).apply {
    name = "Aller"
    age = 50
}
// view 初始化
mRootView = View.inflate(activity, R.layout.example_view, null).apply {
   tv_cancel.paint.isFakeBoldText = true
   tv_confirm.paint.isFakeBoldText = true
   seek_bar.max = 10
   seek_bar.progress = 0
}

also 函数

also函数的结构实际上和let很像,唯一的区别就是返回值的不一样。let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。
also函数返回的则是传入对象的本身。适用于let函数的任何场景,also函数和let很像,只是唯一的不同点就是let函数最后的返回值是最后一行的返回值而also函数的返回值是返回当前的这个对象。一般可用于多个扩展函数链式调用

fun main() {
    val result = "Tom".also {
        println(it.length)
    }
    println(result) // 打印:Tom
}

内联函数

Kotlin 编译器会将内联函数中的代码在编译时自动替换到调用它的地方,这样就不存在运行时的开销了。

**一般会把高阶函数声明为内联函数,**即在定义高阶函数时加上inline关键字声明,这是一种良好的编程习惯,绝大多数高阶函数是可以直接声明成内联函数的。

参考:
https://blog.csdn.net/LucasXu01/article/details/106163092

inline fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
    val result = operation(num1, num2)
    return result
}

扩展函数

Kotlin 有个特别好用的功能叫扩展,你可以给已有的类去额外添加函数和属性,而且既不需要改源码也不需要写子类。

扩展函数写法

声明一个扩展函数,我们需要用一个 接收者类型 也就是被扩展的类型来作为他的前缀。

参考:https://www.kotlincn.net/docs/reference/extensions.html

下面代码为MutableList添加一个swap 函数:

// 声明
fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // “this”对应该列表
    this[index1] = this[index2]
    this[index2] = tmp
}

// 使用
val list = mutableListOf(1, 2, 3)
list.swap(0, 2) // “swap()”内部的“this”会保存“list”的值

如果一个类定义有一个成员函数与一个扩展函数,而这两个函数又有相同的接收者类型、 相同的名字,并且都适用给定的参数,这种情况总是取成员函数。 例如:

class Example {
    fun printFunctionType() { println("Class method") }
}

fun Example.printFunctionType() { println("Extension function") }

Example().printFunctionType()

输出:
“Class method”。

总结

  • 基础函数:fun 开头声明,有可选参数、命名参数、可变长参数
  • 高阶函数:以函数作为参数或者返回值的函数
  • 扩展函数:可在已有的类增加函数和属性,在和成员函数同名、同参,成员函数优先级更高。
  • 内联函数:高阶函数在运行时会有开销,使用inline内联函数来规避。

你可能感兴趣的:(Android,Kotlin)