kotlin扩展函数
Kotlin的又一大特色
给别人的类添加扩展函数和属性
当我们在一个现有的java或者android项目中,需要添加kotlin的代码,而我们又不能把java等之类的代码全部转重写成kotlin,那会大大降低效率,而kotlin的扩展函数就很好的解决了这个办法。
例如:我要获取字符串的最后一个字符:1
2
3
4fun main() {
println("kotlin".lastChar())
}
fun String.lastChar(): Char = this.get(this.length-1)结果为
1
2n
Process finished with exit code 0在上述演示中,
String
表示接受类型,”kotlin“
表示接受者对象,也就是接受类型的具体实例。然后,lastChar
就是扩展的函数名,后面则是一个表达式体。
这样子,就算为莫个类扩展了方法和属性。
而且,不只是kotlin中,所有java,scale或者Groovy之类的JVM语言编写的都会被编译为java类,也就是都可以为这个类添加扩展。
而且对于扩展函数而言,他就和其他成员变量一样,可以直接使用类中的方法,也就是默认在ths下。因此可以省略他,如下1
fun String.lastChar(): Char = get(length-1)
但是扩展函数是在类之外定义的函数,他不能破坏类的封装性,所以相对于成员变量而言,扩展函数并不能访问私有或者受保护的变量。
扩展函数也需要从外部导入
扩展函数并不会自动的在全局生效,尽管智能的IDE会帮你自动导入,但是你仍然需要明白,你必须通过import strings.lastChar
类似上述模板的样子来导入方法。从java中调用扩展函数
以上述的扩展函数为例1
char c = StringUtilKt.lastChar("JAVA")
这里,StringUtilKt是指包含这个属性的包名。从java中调用扩展函数时,他就和调用静态方法一样,只是这个接受者对象需要作为第一个参数传递到该方法中。形式如上。
扩展函数不能重写
因为在通过JVM编译后,他实际上会被转化为静态函数,所以扩展函数重写并没有什么意义,如果重写了该方法,最后调用该方法只取决于是否该对象的静态类型,而不是他的运行时类型
如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21open class A(val a: String) {
fun showA() {
println(a)
}
}
class AA(a:String):A(a){
}
fun A.showDoubleA() {
println(a)
println(a)
}
fun AA.showDoubleA() {
println(a)
println(a)
println(a)
}
fun main(){
val test:A = AA("2")
test.showDoubleA()
}
//输出结果为22扩展属性
除了扩展方法外,你也可以扩展属性
但是同样的,他会在JVM编译器中转化为静态属性,
如果你定义的是val方法,那么这个属性将是不可变的,你需要自己去定义他的get方法,
如果用var去定义,那你同时需要定义他的get和set方法。
因为他没有默认支持的字段,也没有默认的get方法,同理,初始化也不可以,因为没有地方存储初始值
通过java来调用扩展属性的话,必须使用get和set方法来获取,不能直接操作属性