扩展被静态解析
扩展被理解为静态的,扩展并不会修改被扩展的类。通过定义扩展,你并没有向类添加新的成员,但是仅仅是将新的函数作用的扩展类型的调用上。
扩展被声明为静态的,这意味着被调用的扩展函数取决于函数调用的表达式类型而不是运行时计算结果的类型,比如:
open class C
class D: C()
fun C.foo() = "c"
fun D.foo() = "d"
fun printFoo(c: C) {
println(c.foo())
}
printFoo(D())
在上面的例子中,最终打印出来的值为“c”而不是“d”,因为申明的扩展函数依赖于其参数的具体类型C而不是运行时的类型D。
另外需要注意的是如果一个类拥有一个成员函数和一个扩展函数,但是这个扩展函数有一样的接收类型、一样的名字和一样的参数类型,那么在调用时,总是优先调用成员函数。
class C {
fun foo() { println("member") }
}
fun C.foo() { println("extension") }
在此有个需要注意的问题,这两个函数虽然看起来一样。但是调用方式是不同的。
前者在Java中的的调用:
C c = new C();
c.foo();
后者在Java中的调用:
ExtensionFunctionKt.foo(new C());
在Kotlin中的调用统一如下:
var c = C();
c.foo()
最后,可以利用扩展函数的这个特性来扩展函数同名但是签名信息不同的方。
class C {
fun foo() { println("member") }
}
fun C.foo(i: Int) { println("extension") }
C().foo(1)将会打印出 "extension"。