给别的类添加方法:扩展函数
有时候我们会有想给一个类添加上某些方法,但是我们并没有这个类的添加方法的权限,或者是说,这个类是官方提供给我们的。在java中是不可能实现的了,但是在kotlin中确实可以做到的,这个就是kotlin中的扩展方法。
在java中,我们通常会利用静态方法来书写某些工具类,但是在kotlin中的话,我们就可以利用扩展函数来实现。采用了扩展函数的优势是不需要将当前的对象当做参数传入,就像是调用当前对象的方法一样自然。
定义一个扩展函数
//给String类添加了一个printlnForExtend的扩展方法fun String.printlnForExtend(){println(this)}
把要扩展的类或者接口名称,放到即将添加的函数前面,这个类的名称为接收者类型 。用来调用这个扩展函数的那个对象叫做 接收者对象 。

在这个例子中,我们的
String就是接收者类型,哪个字符串调用这个方法,则该字符串就是接收者对象。我们调用试试看:
fun main(args: Array<String>) {
"laotie".printlnForExtend()
}
打印结果:
laotie
我们的扩展函数就像是 String 里面的内部方法一样,使用起来感觉很舒适。但是我们需要注意的是:扩展方法不能破坏原有类的封装性,也就是说不能访问到私有或者是受保护的类。
导入扩展函数
一般来说,我们只需要调用就行了,编译器(如Android studio)默认会帮助我们进行扩展函数的导入。那导入这一章节是不是就结束了呢?其实还有点需要提一下的。就是我们可以使用关键字 as 来修改导入的类或者函数的名称:
//将扩展方法的名称改为了print
import net.println.kotlin.chapter5.builtins.printlnForExtend as print
"laotie".print()
在不同的包里面,如果有重名的函数的话,就可以采用这种修改方式。
从java中调用扩展函数
//MainKt是当前扩展方法所在文件的文件名
MainKt.printlnForExtend("laotie");
不可重写的扩展函数
不论是在java中还是在kotlin中,重写成员函数是一件很平常的事情。但是,不能重写扩展函数。
open class View {
open fun click(){
println("我是Viiew")
}
}
class Button :View() {
override fun click(){
println("我是Button")
}
}
//给View定义一个名叫showOff的扩展方法
fun View.showOff(){
println(" i am a view")
}
//给Button定义一个名叫showOff的扩展方法
fun Button.showOff(){
println(" i am a button")
}
fun main(args: Array<String>) {
val view: View = Button()
view.click()
view.showOff()
}
打印结果:
我是Button
i am a view
可以看到上面的例子,我们分别定义了两个类 view 和 Button ,给 view 和 Button 都定义了叫做 showOff 的扩展方法。我们在执行打印的时候,定义了一个 Button 的对象,但是 View 类型的,这个对象分别调用了 showOff 和 click 的方法,从打印结果里面可以看出,click 调用的是子类 Button 的方法,但是 showOff 则还是父类 View 的方法,这就证明了扩展方法是不能被重写的。
扩展属性
声明一个扩展属性
val String.lastChar : Char
get() = get(length -1)
可以看到,和扩展函数一样,扩展属性也像接收者的一个普通的成员属性一样。这里,必须定义getter 函数,因为没有支持字段,因此没有默认 getter 的实现,同理,初始化也不可以:因为没有地方存储初始值。
上面我们声明的是一个不可变的扩展属性,用的是 val 修饰符修饰的,我们还可以定义一个可变属性:
//给StringBuilder定义了一个名叫lastChar的扩展属性,并实现了getter和setter方法
var StringBuilder.lastChar: Char
get() = get(length - 1)
set(value: Char) {
this.setCharAt(length - 1, value)
}
fun main(args: Array<String>) {
println("laotie".lastChar)
var builder = StringBuilder("laotie-")
builder.lastChar = '+'
println(builder)
}
打印结果:
e
laotie+
在java中调用扩展属性的话,需要显示的调用 getter 函数。
