小狮子的Kotlin学习之路(十四)

前面,我们学习了Kotlin类和对象的相关内容,接下来我们学习Kotlin函数。其实函数function我们在之前已经有接触过,只是没有详细的去学习。

接触最早的要数main()函数了。在编写Hello World程序时,我们就接触了函数,它是一个程序入口函数。接下来,我们全方位了解一下Kotlin函数。

函数的声明语法为:

modifier fun functionName(): Unit {}

其中,functionName()的括弧中可以包含0-N(N < 5, 当参数多于5个时,建议使用数据类)个参数,参数必须声明它的类型,如

    fun max(a: Int, b: Int): Int {

        return if (a > b) a else b
    }

Int为函数的返回值类型。返回值可以是任意对象,而Unit表示函数没有返回值,当返回值是Unit类型时,Unit可以省略(在使用表达式函数时,依赖编译器的类型推断,也可以省略返回值类型)。

    fun sayHello() {

        println("Hello World.")
    } 

当函数有返回值时,必须有return返回一个结果或使用函数表达式。

  fun maxInt(a: Int, b: Int) = if (a > b) a else b

基于Kotlin的自动类型推断能力,和定义属性一样,由编译器自动推断其类型。fun maxInt(a: Int, b: Int)。在这里,我们不仅省略了return关键字,而且省略了返回值类型Int

针对函数的参数,在Kotlin中,参数是可以提供默认值的

  fun maxIntWithDefault(a: Int, b: Int = 2) = if (a > b) a else b

此时,我们在调用该函数时,如果需要使用默认值,可以不传入第二个参数。

需要注意的是,在面向对象的编程中,函数表示的是一个对象的行为,所以函数的名称必须具有一定代表意义的动词。如run()eat()add(a: Int, b: Int): Int

声明好函数之后,需要调用函数,才能够执行它。

fun main() {

    KotlinFunc().sayHello()
}

函数的调用使用.。当函数定义在类中时,我们调用对象需要先创建类的对象。

创建类的方式为className()。当函数定义在Kotlin File中函数时,可以直接调用。

fun main() {

    show()
}

fun show() {
    println("This is show function in kt file.")
}

调用带有默认参数的函数时,可以这样调用。

    val result = KotlinFunc().maxIntWithDefault(1)

    print(result)

当然了,不使用默认值时,必须传入所有参数。

但是,如果有默认值的参数在无默认值参数的前面,调用时必须使用具名参数来调用,否则编译器将因为未提供足够的参数而报错无法编译通过。所谓具名参数,就是通过函数参数的签名 = value的方式明确指定具体参数的值,如。

    fun maxIntWithDefault(a: Int = 1, b: Int) = if (a > b) a else b

    val result = KotlinFunc().maxIntWithDefault(b = 2)
    print(result)

此时,参数a使用其默认值1

需要注意的是,当类继成含有默认值函数的父类时,重写父类函数时,必须从函数签名中去除参数默认值。

    open class Operator {

        open fun add(a: Int, b: Int = 2) = a + b
    }
    class SubOperator: Operator() {
        override fun add(a: Int, b: Int): Int = a + b
    }

但调用时,依旧可以使用有参数默认值的方式调用。

    SubOperator().add(1)

需要说的是,在多参数或多默认值参数的函数调用时,使用具名参数,可以使得代码更加易读。

    fun loadConfig(path: String, fileName: String = "config", type: String = ".txt") {

        println("path = $path, fileName = $fileName, type = $type")
        // load the file.
    }
    
    KotlinFunc().loadConfig(path = "./kotlin", fileName = "config", type = ".xml")

说完参数,Kotlin中存在一个可变数量参数用vararg修饰。可变数量参数一般用于一个函数的最后一个参数,表示可以有多个同样类型的参数,个数可以不定,相当于一个大小不确定的数组。

    fun printNumber(vararg numbers: Int) {

        for (number in numbers) {
            println(number)
        }
    }

那我们如何来调用这个参数呢?

    KotlinFunc().printNumber(1, 2, 3)

如果我们要打印的数据保存在一个数组中,那我们怎么调用这个函数输出数组的元素呢?这就引出Kotlin中的*(伸展)操作符。

    val myArray = IntArray(6) {

        1
    }
    KotlinFunc().printNumber(*myArray)

这里做一个解释。我们创建了一个IntArray并且用1初始化它的所有元素,也就是说,数组里是6个1。紧接着,我们使用fun printNumber(vararg numbers: Int)函数输出了内容,这里,就用到了*操作符。它的作用就是把一个数组伸展开来,变成用每个元素组成的可变数量参数。

当然,我们在某些情况下,函数的传入参数为多个类型一致的参数时,也可以使用同样的方式进行参数传入。

Kotlin中,某些操作符被使用函数进行重写,比如+-等。比如a + b可以写成

    fun sum(a: Int, b: Int) = a.plus(b)

另外,更加特殊的是,Kotlin提供了中缀表达式函数,举个例子

    val a = 1000
    println(a shl 1)

除了移位操作符之外,在循环中,我们见到的表示范围的until也是中缀表达式函数。

不过,中缀表达式函数,有它的一些特殊点。

  • 它们必须是成员函数或扩展函数

  • 它们必须只有一个参数

  • 其参数不得接受可变数量参数且不能有默认值

扩展函数后面我们单独说,先来看一下成员函数

说到成员函数,我们就不得不说函数的作用域。关于函数的作用域,我们从字面意思就能够理解,所定义的就是哪些函数在什么范围内能够使用,哪些范围内不能使用。

Kotlin中,函数可以写在任意地方,没有严格的限制。比如在文件中,我们可以写在顶层,如我们之前经常使用的main()函数。写在顶层的函数,调用是不需要创建对象的,可以直接调用。Kotlin库中,有很多写在顶层的函数。比如:

public inline fun repeat(times: Int, action: (Int) -> Unit) {

    contract { callsInPlace(action) }
    for (index in 0 until times) {
        action(index)
    }
}

这是存于Standard.kt中的一个库函数,它是一个高阶函数, 而且是一个内联函数。关于高阶函数和内联函数后面会单独学习,它的用处很大,在某些时候能够很大程度地使代码简化。

当然,函数除了写在顶层外,还可以写在类、伴生对象、对象、以及函数中,另外还有后面我们要学习的扩展函数。

写在类中的函数,称作成员函数,对于成员函数,我们之前写过很多了,这次就不举例子了。成员函数也是最常见和常用的函数。

对象和伴生对象,我们在下一篇的对象和对象表达式中再深入学习,那函数写在函数中,是什么意思呢?

    fun sum(a: Int, b: String): Int {

        fun convert(b: String): Int {
            return b.toInt()
        }
        return a.plus(convert(b))
    }

因为是示例程序,所以写的很简单,在实际应用中肯定不是这么个用法,否则代码就很啰嗦和冗余了,不是优秀的编程实践。

我们看到,在sum函数中,定义了一个convert函数。需要注意的是,写在函数中的函数,称作局部函数。当然,它的作用域就只能是在这个函数内,函数外部是无法调用的。

针对函数的基本内容,就先到这里咯,下一篇,我们学习高阶函数。


关注微信公众号,一起学习讨论

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值