trait,线性化

近来重新拾起scala,看到trait,要总结一下,因为这玩意的逻辑不是那么明显,很容易就忘了

下文出现的“父子关系”指的是可能跨越多代的继承关系

首先要理解线性化是怎么做的。线性化简单来说就是,写在越后面的trait的“优先级”越大。
举个例子,假设某个类Z线性化以后的结果是
A  B  C  D  E  F  Z


然后,假设有一个方法叫m1,从左到右地扫描上面的“链”,这个m1首先出现在B,那么我们知道,B的后代是可以有机会override这个m1的。
我们从B开始,继续向右扫描,寻找“和B是父子关系”并且“override了m1”的trait,假设是D和F,F的位置在D的后面,所以,当我们调用Z的m1,其实就是在调用F的m1。很有趣的事情是,当你将一个Z类型的对象转型为类型D,然后去调用m1,执行的是F的m1,但是D和F并没有父子关系,也就是说,这是一种“兄弟之间的覆写行为”,与java做对比的话,java里面的override,必然是“父子之间的覆写行为”,因为java的override只发生在类与类之间,java的继承的特点是单一继承,而scala的trait的继承,其实是多重继承那一套。


不禁要问,如果在上面的链,存在一个trait,譬如说 C,它也有一个叫m1的方法,但是它跟B没有父子关系,那会怎么样?
答案就是:编译器不会让你的代码通过!因为这是一种”意外发生的命名冲突“,而override是“继承链中意图明确的覆写”。
那要怎么解决?解决的办法就是,你要在Z里面定义一个Z自己的override def m1。为什么这样就可以了?
当你在Z里面定义了一个 override def m1 的时候,你实际上是在用Z的m1来覆写B和C里的m1。C和B的m1是不能互相覆盖的,因为它们的m1根本没有“血缘关系”,只是恰好取了同一个名字而已,但是,Z是B的后代,Z也是C的后代,所以,Z可以覆写B的方法,也可以覆写C的方法。








转载于:https://my.oschina.net/mustang/blog/159635

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值