Kotlin之扩展
- 2019 年 10 月 7 日
- 筆記
目前大多说的高级语言在对已有的class进行扩展大多采用继承或者装饰器的方式,但是这些方式大都会破坏原类,对整个项目来说是一种侵入式极强的方式……Kotlin在function这方面吸取了一些动态语言(OC)仿照姊妹篇swift的方式可以对已有的class进行方法扩展达到了可以在不重新已有类修改代码或者使用子类的方式对类进行功能的扩展……
声明一个扩展方法
对于一个方法可定是有接收者,因此在方法扩展需要添加class的声明啦,我们看如下代码:
class Animal{} fun Animal.move() { }
我们首先声明了一个class叫做Animal,然后扩展一个move的能力,那么怎么使用这个能力呢?
val animal = Animal() animal.move()
可以看出它与成员方法并没有什么不同之处。其实本质还是有区别的,我们对上栗进行修改,class内部添加一个move方法
class Animal { fun move() { } } fun Animal.move() { }
这时候假如调用move的时候如何呢,使用的是扩展方法还是成员方法呢?
如果一个类定义有一个成员函数与一个扩展函数,而这两个函数又有相同的接收者类型、 相同的名字,并且都适用给定的参数,这种情况总是取成员函数
扩展为静态解析
扩展不是原有类进行修改来实现扩展的,它仅仅是可以通过类的实例化之后通过点语法调用的一个函数而非是类实例的一个成员方法。更确切的说它是根据代码声明处的那个类型来决定怎么调用分发的而不是由动态运行时所属的类型决定怎么分发的
上面的描述整体有点绕,但是整体就是说调用时有程序走到哪里爵溪成代码代码声明的是什么类型就通过这个类型去搜寻对应的类对应的方法扩展
我们修改代码如下:
open class Animal { } //子类 class Dog: Animal() { } //子类 class Duck : Animal() { } //扩展 fun Dog.move() { } //扩展 fun Duck.move() { } fun Animal.move() { } //调用 var animal: Animal = Dog() animal.move()
当我们调用move时会调用哪个的move扩展呢?下面我们复盘一下
1 声明变量为Animal类型
2 动态实例化Dog实例
3 变量调用move
根据扩展的静态解析规则来说调用时回溯到变量声明之处为Animal因此调用Animal申明的扩展方法move
扩展属性
扩展属性与扩展方法类似
val <T> List<T>.lastIndex: Int get() = size - 1
扩展作用域
杜宇扩展要想挎包访问,需要在包内import扩展出的方法