在Kotlin中,为什么会有扩展?因为可以让使用者(或定义者)不修改即有源代码的情况下,同时又不借助于装饰模式等任何一种设计模式的情况下, 以一种比较快捷和方便的方式去为一个即有的类增加功能,而提供的这样的一种手段。Kotlin通过扩展可以很好的解决Java中充斥的各种辅助类问题。
- 扩展函数(方法)
如下所示,是一个扩展函数的例子:
/**
* 扩展性,extension
* 在不改变原有类结构的情况下,给这个类动态的增加一些额外的功能
*/
class ExtensionTest {
fun add(a: Int, b: Int) = a + b
fun sub(a: Int, b: Int) = a - b
}
/**
* ExtensionTest类的扩展方法
*/
fun ExtensionTest.mul(a: Int, b: Int) = a * b
fun main(args: Array<String>) {
var extensionTest = ExtensionTest();
println(extensionTest.add(1, 3))
println(extensionTest.sub(2, 2))
println(extensionTest.mul(3, 1))
}
输出结果:
4
0
3
- 扩展本身并不会真正的修改目标类,也就是说它并不会在目录类中插入新的属性或方法;
- 扩展函数的解析是静态分发的,而不是动态的,即不支持多态,调用只取决于对象的声明类型;
- 调用是由对象的声明类型所决定的,而不是由对象的实际类型决定。
如下所示:
open class ClassA
class ClassB: ClassA()
fun ClassA.a() = "a"
fun ClassB.a() = "b"
fun myPrint(a: ClassA) {
println(a.a())
}
fun main(args: Array<String>) {
myPrint(ClassA())
}
输出结果:
a
// 由ClassA改为ClassB,输出结果也是a
fun main(args: Array<String>) {
myPrint(ClassB())
}
输出结果:
a
如果一个类有了某一个方法,然后对这个类进行扩展,扩展的方法名及签名都完全一样,类里面即有的方法优先级最高。注:不过实际情况不会出现,不会对类扩展一个跟类里包含的方法一样的方法。如下所示:
class ClassC {
fun foo() {
println("cc.foo")
}
}
fun ClassC.foo() {
println("cc.foo2")
}
fun main(args: Array<String>) {
ClassC().foo()
}
输出结果:
cc.foo
- 扩展属性
如下所示,是一个扩展属性的例子:
class ExtensionProperty
val ExtensionProperty.name: String
get() = "hello"
fun main(args: Array<String>) {
var extensionProperty = ExtensionProperty()
println(extensionProperty.name)
}
输出结果:
hello
- 伴生对象扩展
如下所示,是一个伴生对象扩展的例子:
class CompanionExtension {
companion object MyObject {
}
}
fun CompanionExtension.MyObject.method() {
println("hello world!")
}
fun main(args: Array<String>) {
CompanionExtension.method()
}
输出结果:
hello world!
- 扩展的作用域
- 扩展函数所定义在的类实例叫做分发接收者(dispatch receiver);
- 扩展函数所扩展的那个类的实例叫做扩展接收者(extension receiver);
- 当以上两个名字出现冲突时,扩展接收者的优先级最高。
如下所示:
class Demo {
fun method() {
println("demo method")
}
}
class Demo2() {
fun method2() {
}
fun Demo.hello() {
method()
method2()
}
fun world(demo: Demo) {
demo.hello()
}
fun Demo.output() {
println(toString())
println(this@Demo2.toString())
}
fun test() {
var demo = Demo()
demo.output()
}
}
fun main(args: Array<String>) {
Demo2().test()
}
输出结果:
com.ssy.kotlin.demo.Demo@6e0be858
com.ssy.kotlin.demo.Demo2@61bbe9ba
注:this@Demo2,Kotlin提供的特殊语法,是为了解决函数(方法)重名的问题,this@分发接收者的名字。