Kotlin 同 C# 类似,能够无需继承该类或使用像装饰者这样的任何类型的设计模式,就能扩展一个类的新功能。 完成这种功能的特殊方法叫做 扩展 。Kotlin 支持 扩展函数 与 扩展属性。
扩展函数
声明一个扩展函数,需要用一个 接收者类型, 也就是被扩展的类型来作为他的前缀。
- 以下示例代码是为String类添加一个扩展函数,判断是否有效
fun String.isValidPwd(): Boolean {
return this.isNotEmpty() && this.length < 20
}
这个
this
关键字在扩展函数内部对应到接收者对象(传过来的在点符号前的对象)
- 扩展函数支持泛型
- 扩展不能真正的修改所扩展的类,并没有在一个类中插入新成员, 仅仅是可以通过该类型的变量用点表达式去调用这个新函数。
- 扩展是静态解析的,他只会根据定义的类型进行接卸调用,即他们不是根据接收者类型的虚方法。
open class A
class B: A()
fun A.printMsg() = "This is A print"
fun B.printMsg() = "This is B print"
fun printMsg(a: A) {
println(a.printMsg())
}
fun main(args: Array<String>) {
printMsg(B())
}
以上示例中,
printMsg()
方法定义时参数类型是A,实际调用是传入子类B的对象,但是实际输出却是调用了A的扩展方法。
- 如果扩展函数与类的成员函数具有相同的签名,调用时总是调用成员函数。
open class A
class B: A() {
fun printMsg() = "This is inside B print"
}
fun A.printMsg() = "This is A print"
fun B.printMsg() = "This is B print"
fun main(args: Array<String>) {
println(B().printMsg())
}
以上示例中,扩展函数与类的成员函数具有相同的签名,调用时总是调用成员函数。
扩展属性
跟扩展函数一样,Kotlin中支持扩展属性。
- 因扩展属性并没有在类中插入属性,所以幕后字段是无效的。
- 扩展字段不能有初始化器(原因如上所述),只能提供显式的
getter
/setter
class B {
}
val B.desc: String
get() {
return "This is a desc"
}
val B.test: String = "This is a test" // 扩展字段不能有初始化器,所以这样定义是错误的
扩展的作用域
- 一般在顶层(及包内)定义扩展,将会在整个包内可以访问
- 如果需要访问其他包定义的扩展,可以通过引入包的方式调用