Kotlin 能够扩展一个类的新功能而无需继承该类或者使用像装饰者这样的设计模式。 这通过叫做 扩展 的特殊声明完成。 例如,你可以为一个你不能修改的、来自第三方库中的类编写一个新的函数。 这个新增的函数就像那个原始类本来就有的函数一样,可以用普通的方法调用。 这种机制称为 扩展函数 。此外,也有 扩展属性 , 允许你为一个已经存在的类添加新的属性。
扩展函数
声明一个扩展函数,我们需要用一个 接收者类型 也就是被扩展的类型来作为他的前缀
扩展函数如果定义在类中,只能在类中使用,外界无法调用此扩展
fun String.hello():String{
return "${this}++welcome"
}
调用的扩展函数是由函数调用所在的表达式的类型来决定的, 而不是由表达式运行时求值结果决定的(例如:方法参数是父类类型,但是传递的是子类类型,实际上调用的还是父类的扩展)
fun Shape.getName():String{
return "Shape"
}
class Rectangle:Shape()
fun Rectangle.getName() = "Rectangle"
fun printlnName(shape: Shape){
println(shape.getName())
}
printlnName(Rectangle())//Shape
调用的还是Shape中的方法,因为调用的扩展函数只取决于shape的声明类型
如果一个类定义有一个成员函数和扩展函数,并且这两个函数具有相同的名字,相同的参数和返回值,调用函数时,总是调用成员函数
class Hello{
fun say():String{
return "hello say"
}
}
fun Hello.say():String{
return "extension fun hello say"
}
println(Hello().say())//hello say
扩展属性
扩展属性的field是无效的,它们的行为只能通过显示setter/getter定义
val String.empty: Boolean
get() {
return this.isEmpty()
}
伴生对象的扩展
类中有伴生对象时,可以对伴生对象定义扩展属性和函数,使用类名调用扩展函数和属性
class ExtensionFun {
companion object{
fun talk(){
println("talk")
}
}
}
fun ExtensionFun.Companion.exTalk(){
println("exTalk")
}
ExtensionFun.exTalk()
覆盖父类的扩展
成员扩展可以使用open让子类覆盖,也就是子类可以复写父类的扩展函数
open class Base { }
class Derived : Base() { }
open class BaseCaller {
open fun Base.printFunctionInfo() {
println("Base extension function in BaseCaller")
}
open fun Derived.printFunctionInfo() {
println("Derived extension function in BaseCaller")
}
fun call(b: Base) {
b.printFunctionInfo() // 调用扩展函数
}
}
class DerivedCaller: BaseCaller() {
override fun Base.printFunctionInfo() {
println("Base extension function in DerivedCaller")
}
override fun Derived.printFunctionInfo() {
println("Derived extension function in DerivedCaller")
}
}
fun main() {
BaseCaller().call(Base()) // “Base extension function in BaseCaller”
DerivedCaller().call(Base()) // “Base extension function in DerivedCaller”——分发接收者虚拟解析
DerivedCaller().call(Derived()) // “Base extension function in DerivedCaller”——扩展接收者静态解析
}