【笔记】Kotlin的函数

前言

Kotlin的函数学习笔记

定义函数

无形参

1
2
3
fun 函数名() {
...
}

有形参

  • 函数的形参默认为常量,不能改变值
1
2
3
fun 函数名(形参名: 数据类型) {
...
}

无返回值

1
2
3
fun 函数名() {
...
}

Unit:没有返回值的类型

1
2
3
fun 函数名(): Unit {
...
}

有返回值

1
2
3
4
5
fun 函数名(): 返回值类型 {
...

return 返回值
}

调用函数

无实参

1
函数名()

有实参

1
函数名(实参)

无返回值

1
函数名()

有返回值

1
val 变量名 = 函数名()

函数形参的默认值

1
2
3
4
5
fun 函数名(形参名: 数据类型 = 默认值) {
...
}

函数名()

为指定形参传递实参

1
2
3
4
5
fun 函数名(形参名: 数据类型 = 默认值) {
...
}

函数名(形参名 = 实参)

函数体只有一个表达式

1
fun 函数名(形参名: 数据类型) = 没有返回值的表达式
1
fun 函数名(形参名: 数据类型) = 可以自动推断返回值类型的有返回值的表达式
1
fun 函数名(形参名: 数据类型): 返回值类型 = 有返回值的表达式

全局变量

  • 在函数外部定义的变量是全局变量
  • 可以为var定义的变量和val定义的常量定义get()方法,每当获取变量值时get()方法都会被自动调用
  • 可以为var定义的变量定义set()方法,每当设置变量值时set()方法都会被自动调用
  • get()方法和set()方法可以使用field关键字获取当前变量
1
2
3
4
5
6
7
8
9
10
var 变量名: 数据类型 = 值
get() = field
set(value) {
field = value
}

fun main() {
println(变量名)
变量名 = 值
}
1
2
3
4
5
6
val 常量名: 数据类型 = 值
get() = field

fun main() {
println(常量名)
}

递归函数

  • 通过tailrec关键字修饰的函数可以进行递归操作
1
2
3
tailrec fun 函数名(形参名: 数据类型): 返回值类型 {
return 函数名(实参)
}

通过变量存储函数(Lambda表达式)

无形参

1
2
3
var 变量名: () -> Unit = {
...
}

代码块只有一行代码

1
var 变量名: () -> Unit = println()

有形参

1
2
3
var 变量名: (形参类型) -> Unit = { (形参名) ->
...
}

通过it关键字指代函数的形参

  • 省略只有一个形参的形参名的语法糖
1
2
3
var 变量名: (形参类型) -> Unit = {
println(it)
}
  • 如果函数有不止一个形参则不能使用it
1
2
3
4
var 变量名: (形参类型1, 形参类型2) -> Unit { (形参名1, 形参名2) ->
println(形参名1)
println(形参名2)
}

通过下划线跳过形参

1
2
3
var 变量名: (形参类型1, 形参类型2) -> Unit { (_, 形参名2) ->
println(形参名2)
}

无返回值

1
2
3
var 变量名: () -> Unit = {
...
}

有返回值

  • Lambda表达式不能通过return关键字返回值,最后一个表达式的结果即为返回值
1
2
3
4
var 变量名: () -> 返回值类型 = {
...
返回值
}

通过变量存储函数(匿名函数)

无形参

1
2
3
var 变量名: () -> Unit = fun(): Unit {
...
}

有形参

1
2
3
var 变量名: (形参类型) -> Unit = fun(形参名: 数据类型): Unit {
...
}

无返回值

1
2
3
var 变量名: () -> Unit = fun(): Unit {
...
}

有返回值

1
2
3
4
var 变量名: () -> 返回值类型 = fun(): 返回值类型 {
...
return 返回值
}

函数作为函数形参

只有一个形参

  • 如果只有一个形参,且是函数类型,那么可以在实参传递时省略小括号
1
2
3
4
5
6
7
8
9
10
fun 函数名(形参名: (形参类型) -> 返回值类型) {
...
}

fun main() {
函数名 {
println(it)
返回值
}
}

有多个形参

  • 如果函数类型的形参是最后一个形参,那么可以在实参传递时省略小括号
1
2
3
4
5
6
7
8
9
10
fun 函数名(形参名1: Int, 形参名2: (形参类型1, 形参类型2) -> 返回值类型) {
...
}

fun main() {
函数名 (0) {
println(it)
返回值
}
}
  • 如果函数类型的形参不是最后一个形参,那么不可以在实参传递时省略小括号
1
2
3
4
5
6
7
8
9
10
fun 函数名(形参名1: (形参类型1, 形参类型2) -> 返回值类型, 形参名2: Int) {
...
}

fun main() {
函数名 ({
println(it)
返回值
}, 0)
}

函数作为返回值

1
2
3
fun 函数名(): (形参类型) -> 函数返回值类型 {
return fun(形参名: 数据类型): 函数返回值类型 {}
}

标签限定返回

  • 只返回lambda而不返回外层函数
1
2
3
val func: () -> Unit = 标签名@{
return@标签名
}
  • 没有指定标签名时默认为变量名
1
2
3
4
5
6
7
8
9
10
fun 函数名(形参名: () -> Int) {
var 变量名 = 形参名()
}

fun main() {
函数名 {
if (布尔表达式) return@函数名 提前返回的返回值
正常返回的返回值
}
}

内联函数

  • 通过inline关键字修饰的函数是内联函数
  • 在编译时,内联函数的调用位置会改为散列内联函数的函数体
1
2
3
4
5
6
7
fun main() {
函数名()
}

inline fun 函数名() {
println()
}
1
2
3
fun main() {
println()
}
  • 如果内联函数的形参是函数类型,且这个函数不希望被内联,可以通过noinline关键字修饰,表示不内联
1
2
3
4
5
6
7
8
9
fun main() {
函数名 {
...
}
}

inline fun 函数名(noinline 形参名: () -> Unit) {
println()
}

可变长参数

1
2
3
4
5
fun 函数名(vararg 形参名: 数据类型) {
...
}

函数名(1, 2, 3)

可变长参数在普通参数后面

1
2
3
4
5
fun 函数名(形参名1: String, vararg 形参名2: Int) {
...
}

函数名("1", 2, 3)

可变长参数在普通参数前面

1
2
3
4
5
fun 函数名(vararg 形参名1: Int, 形参名2: String) {
...
}

函数名(1, 2, 形参名2 = "3")

可变长参数形参转换为数组

1
2
3
4
5
fun 函数名(vararg 形参名: 数据类型) {
var arr: Array<数据类型> = 形参名
}

函数名(1, 2, 3)

数组转换为可变长参数实参

1
2
3
4
5
6
fun 函数名(vararg 形参名: 数据类型) {
...
}

var arr = arrayOf(1, 2, 3)
函数名(*arr)

完成

参考文献

哔哩哔哩——青空の霞光