函数的基本用法

函数的定义

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

 其中Unit等价于Java的void函数返回值为Unit,可省略。

函数的参数列表如果是多个参数的话使用逗号分隔。

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

函数用法

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

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

调用成员函数使用点表示法

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

val person = Person()
person.double(2)

函数的参数

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

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

默认参数

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

fun main() {
    defaultParameter(5, "Hello", 5L)
    defaultParameter(6, "hello")  // 最后一参数不传,就会使用默认值
    
    // 不传第一个和最后一个,指定y代表的意思是给形参y赋值
    // 如果不指定,编译器就会不知道"hello"是赋值给哪个参数的
    defaultParameter(y = "hello")  // 最后一参数不传,就会使用默认值

}

// 默认参数,默认值必须放到最后,当不传的时候,最后参数是就会按照顺序依次使用默认值(有默认值的情况下)
fun defaultParameter(x: Int = 5, y: String, z: Long = 0L) { 
    println(x)
    println(y)
    println(z)
}

如果一个默认参数在一个无默认值的参数之前,那么该默认值只能通过使用具名参数调用该函数来使用:

fun foo(
    bar: Int = 0, 
    baz: Int,
) { /*……*/ }

foo(baz = 1) // 使用默认值 bar = 0

如果在默认参数之后的最后一个参数是 lambda 表达式,那么它既可以作为具名参数在括号内传入,也可以在括号外传入:

fun foo(
    bar: Int = 0,
    baz: Int = 1,
    qux: () -> Unit,
) { /*……*/ }

foo(1) { println("hello") }     // 使用默认值 baz = 1
foo(qux = { println("hello") }) // 使用两个默认值 bar = 0 与 baz = 1
foo { println("hello") }        // 使用两个默认值 bar = 0 与 baz = 1

覆盖方法总是使用与基类型方法相同的默认参数值。 当覆盖一个带有默认参数值的方法时,必须从签名中省略默认参数值:

open class A {
    open fun foo(i: Int = 10) { /*……*/ }
}

class B : A() {
    override fun foo(i: Int) { /*……*/ }  // 不能有默认值
}

变长参数

这里的args参数就跟listOf(1,2,3)是一样的

fun main() {
    cityName("1", "2", "3")  // 调用后输出结果是: [1, 2, 3]
}

// 变长参数,用vararg标识,都是String类型
fun cityName(vararg args: String) {
    println(args.contentToString())
}

函数的返回值

多返回值

多返回值是指:函数的返回值可以是多个的并且个数和类型是确定的

fun main() {
    val (a, b, c) = multiReturnValues()
    println(a)
    
    val m = a + b  // m为Long类型
    val n = b + c  // n为double类型
    println(m) // 输出结果: 4
    println(n)  // 输出结果:7.0

}


fun multiReturnValues(): Triple<Int, Long, Double> {
    return Triple(1, 3L, 4.0)
}

函数的类型(方法 & 函数)

方法可以认为是函数的一种特殊类型,从形式上,有receiver的函数即为方法, receiver就是类的实例

fun foo1() { TODO() }       // () -> Unit
fun foo2(p0: Int): String { TODO() } // (Int) -> String, 函数接收的是一个Int类型的值,返回的是一个String类型的值

在Kotlin中可以直接定义函数,不用定义在类中;定义在类中的函数其实就是叫方法,属于所在类的方法

// Persion 就是work方法的receiver, 也就是说放在一个类里面的函数就是方法
// 想要调用work必须先创建Persion实例
class Persion {
    fun work(age: Int, name: String): Any{
        TODO()
    }
}

函数的引用

函数的引用类型C语言中的函数指针,可以用于函数传递

下面方法中出现函数的重载,在编译的时候会根据调用函数时的参数匹配来判断调用两个方法中的哪一个,如果判断不出来,编译就会报错

fun foo() { TODO() }       // ::foo就是这个函数的引用 , 使用变量接收   val f:() -> Unit = ::foo  /  val f = ::foo
fun foo(p0: Int): String { TODO() } // ::foo就是这个函数的引用, 使用变量接收   val g:(Int) -> String = ::foo  / val g = ::foo

// work方法的引用就是Persion::work, 使用变量接收  val h:(Persion, Int, String) -> Any = Persion::work  / val h = Persion::work
// val h:(Persion, Int, String) -> Any = Persion::work  等价于  val h:Persion.(Int, 
// 还可以这么写: val h: Function3<Persion, Int, String, Any> = Persion::work
String) -> Any = Persion::work
class Persion {
    fun work(age: Int, name: String): Any{
        TODO()
    }
}

绑定receiver的函数引用

函数和方法的区别,方法可以认为是函数的一种特殊类型。从形式上,有receiver的函数就可以叫做方法。receiver就是类的实例,在这个类实例当中的函数,就叫做方法,比如cityBean.getCity(),cityBean就是receiver,getCity()就被叫做方法。

class Person {
    fun work(age: Int, name: String): Any{
        TODO()
    }
}
val person = Person() // person就是对象的实例
val m:(Int, String) -> Any = person::work // person::work(绑定receiver的函数引用)

其实这段代码就像下面这道数学题一样

将引用传递方法参数当中

class Person {
    fun work(age: Int, name: String): Any{
        TODO()
    }
}
val person:(Person, Int, String) -> Any = Person::work

// 方法当中的参数,也是可以传递方法引用的,如下所示传递类里的方法
fun testPerson(parameter: (Person, Int, String) -> Any) {
    //在这里调用方法
    parameter(Person(), 21, "jacob")
    parameter.invoke(Person(), 21, "jacob")
}

// 将引用传递方法当中
testPerson(person)

匿名函数

Lambda

SAM转换

高阶函数

常见的高阶函数

函数式编程

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐