kotlin的擴展詳解
擴展函數
class ExtensionTest{ //擴展接收者類
fun add(a:Int,b:Int)=a+b
}
fun ExtensionTest.substract(a:Int,b:Int)=a-b //擴展函數
fun main(args: Array<String>) {
val extensionTest=ExtensionTest()
extensionTest.add(2,5)
extensionTest.substract(5,0)
}
擴展函數的解析是靜態的
- 擴展本身並不會真正修改目標類,也就是說它並不會在目標類中插入新的屬性和方法。
- 擴展函數的解析是靜態分發的,即不支持多態,調用只取決於對象的聲明類型。
- 調用是由對象聲明類型所決定的,而不是由對象的實際類型所決定。
open class AA
class BB:AA()
fun AA.a()="a"
fun BB.b()="b"
fun myprint(aa:AA){
println(aa.a())
}
fun main(args: Array<String>) {
myprint(AA()) //打印是“a”
myprint(BB()) //打印還是“a”,,如果是java肯定是“b”,這就是調用只取決於對象的聲明類型,不是初始的實際類型。
}
伴生對象擴展函數
class MyProperty
val MyProperty.name:String
get()="hello
fun main(args: Array<String>) {
var myProperty=MyProperty()
println(myProperty.name)
}
擴展的作用域(類似於java的裝飾模式)
- 擴展函數所定義在的類實例叫做分發接收者(dispatch receiver)
- 擴展函數所擴展的那個類的實例叫做擴展接收者(extension receiver)
- 當以上兩個名字出現衝突時,擴展接收者的優先級最高
class AA{ //擴展接收者類
fun method(){
println("AA method")
}
}
class BB{ //分發接收者
fun method2(){
}
fun AA.hello(){
method() //擴展的是AA,當然能調用AA類裏的方法
method2() //同一個類中當然能調用同級的方法
}
fun word(aa:AA){
aa.hello() //聲明的對象是AA,hello方法是AA的擴展方法,當然能調用
}
fun AA.output(){
println(toString())//調用的是AA類裏的tostring方法,因爲擴展接收者的優先級最高
println([email protected]())//調用的是BB類裏的tostring方法
}
fun test(){
val aa=AA()
aa.output() //擴展函數還是要擴展類的實例調用。
}
}
fun main(args: Array<String>) {
BB().test()
}