函数是以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