kotlin函数的定义和调用

发布时间 2023-10-15 00:16:27作者: LCAC

函数是以fun开头

一、函数的普通例子

这是一个带模板的函数

fun <T> joinToString1(collection: Collection<T>, sep: String, prefix: String, suffix: String): String {
    val result = StringBuilder(prefix)
    for ((index, element) in collection.withIndex()) {
        if (index > 0) result.append(sep)
        result.append(element)
    }
    result.append(suffix)
    return result.toString()
}

我们正常的调用可以是:joinToString1(list, "; ", "(", ")")

但是我们不知道各个参数是什么,那么还需要去函数的定义处查看;kotlin则支持在显示的参数赋值方式:joinToString1(list, ep="; ", prefix="(", suffix=")"),我们既然是显示的,那么我们也可以像python一样,调换参数的顺序:joinToString1(list, prefix="(", sep="; ", suffix=")"),这里把sep的顺序放到prefix后面,但是依旧能正常调用。

 

二、函数可以有默认值

继续以上述为例子,每次调用joinToString1都需要传入所有参数值,如果类似C++增加默认参数值,那么就不需要每次都填写这么多参数

fun <T> joinToString1(collection: Collection<T>, sep: String=";", prefix: String = "(", suffix: String = ")"): String {。。。。。}
这里为sep,prefix和suffix增加了默认参数,那么在调用的时候则可以:joinToString1(list, sep="; ")
这是kotlin特有的,java则需要写一堆的重载函数;那么如果java调用kotlin的时候,尽管这里有写默认值,java层还是需要把所有的参数全都填上
这里有个方案是:增加:@JvmOverloads 注解
@JvmOverloads
fun <T> joinToString1(collection: Collection<T>, sep: String=";", prefix: String = "(", suffix: String = ")"): String {。。。}
那么在编译之后,就会生成多个重载的joinToString1,参数个数从左到右依次增加
 
 三、参数顶层属性
1、属性和函数一样可以放到文件顶层。
    1、val opt = 0
    2、var opt = 0
    3、const val opt = 0 
1中在java中为包含getter方法,2中在java中为包含getter和setter方法,3中在java中显示为:public static final String opt = 0;
在1和2中的opt在类中是被声明为:private static final int opt = 0
 
四、扩展函数和属性
扩展函数是一个类的成员函数,不过它是定义在类的外面。
比如:要为String增加获取最后一个字符的函数,可以类似的增加扩展函数:
fun String.lastChar(): Char = this.get(this.length - 1)
这里的String是接收者的类型,this是接收者的对象
调用:println("Kotlin".lastChar())
则会打印字符串"Kotlin"的最后一个字符:n
但是依旧不可以访问Striing里面的私有及受保护成员
如果在其他的文件中定义的扩展函数,则可以使用导入的方式:import strings.lastChar或者import strings.*方式,也可以使用类似python的导入方式:import strings.lastChar as last 则可以使用:println("Kotlin".last())
 
 注意:扩展函数是静态函数的一个高效语法糖
所以我们扩展函数没法继承和重写
class Base {
    fun testInner() = println("testInner")
}

fun Base.testInner() = println("Base.extern")

// Base().testInner() 结果是:testInner

如果类内部已经有对应的函数,则没法对该类的函数做扩展

 

下面是使用继承的方式,但是因为扩展函数其实是静态函数,所以是不参与动态绑定即运行时的类型

open class Base {
}

class Extern: Base() {
}

fun Base.baseOverride() = println("baseOverride")
fun Extern.baseOverride() = println("externOverride")

val base: Base = Extern()
base.baseOverride()
// 打印结果是:baseOverride