scala super动态绑定

看前须知:

可以先看总结,看不明白再把示例代码复制到编译器中,然后对照着我的文字讲述一步一步看过去。请耐心看下去。否则你就不一定能看懂了。(写了三小时,网上几乎没资料)

如果有更好的关于这方面的资料,希望有朋友能推荐一下。。。我的文笔写出来估计也就我能看懂了。

代码:

object Test {
    def main(args: Array[String]): Unit = {
        val son = new Son
        son.a()
    }
}


class Son extends C with G with E with H with F with B {}

trait H {
    //    def a(): Unit = {
    //        println("A")
    //    }
}

trait A {
    def a(): Unit = {
        println("A")
    }
}

trait B extends A {
    override def a(): Unit = {
        println("B")
        super.a()
    }
}

trait C extends A {
    override def a(): Unit = {
        println("C")
        super.a()
    }
}

trait D extends A {
    override def a(): Unit = {
        println("D")
        super.a()
    }
}

trait E extends D {
    override def a(): Unit = {
        println("E")
        super.a()
    }
}

trait F extends D {
    override def a(): Unit = {
        println("F")
        super.a()
    }
}

trait G extends E {
    override def a(): Unit = {
        println("G")
        super.a()
    }
}

输出结果:

B
F
G
E
D
C
A

描述:

super动态绑定调用链规则:
 1、Son混入或者继承的多个trait中(例子中是B、F、E、G、C)如果有相同的方法a,
 那么这些具有a方法的trait或者class(例子中是B、F、E、G、C)都必须继承自同一个祖宗(例子中是A),并且a方法源头必须是该祖宗(例子中是A)。(不用管是否被重写过,没影响)
 

2、如果在这多个trait中,某个trait的也有相同的a方法,并且不是来自于同一个祖宗(A),那么执行时就会报错。
 比如例子中,Son还混入了H,H与其他trait没有关系,如果在H中添加一个相同签名的a方法,那么程序运行就会报错。

3、继续接着步骤1:此时当调用Son实例的a方法时,使用super就会按动态绑定规则调用混入的trait的a方法。

4、super动态绑定规则:
(1)调用Son的a方法时,Son中没有重写a方法,那么执行的a方法就按定义Son代码时继承和混入的trait的顺序从右往左看。

(2)具有a方法的trait按顺序排列:C、G、E、F、B ,H被去掉了,因为H没有a方法。

(3)然后再看看步骤(2)中剩下的这些trait中是否有继承关系的,如果有存在继承关系的,把存在继承关系中的辈分最小的留下,具体例子:根据代码知道,E和G是有继承关系的,并且是G继承自E,所以G的辈分最小,留下G,去掉E。
此时具有a方法的trait按顺序排列:C、G、F、B。

(4)从右往左执行,调用son的a方法,此时调用的是最右边的B的a方法,打印"B",

(5)然后执行B的super.a(),B左边的是F,F的辈分小于B的辈分,所以此时是从右往左执行,调用F的a方法,打印"F",

(6)然后执行F的super.a(),F左边的是G,G的辈分小于F的辈分,所以此时是从右往左执行,调用G的a方法,打印"G",

(7)然后执行G的super.a(),G左边的是C,C的辈分大于G的辈分,不能像(5)和(6)一样执行,此时G的super.a向上调用G的继承链中的祖宗的a方法,当调用的祖宗与C是同一辈分时,调用完后再继续按照从右往左规则执行。

具体如下:

  • G的继承关系近到远有:G、E、D、A,而C的继承关系近到远有:C、A,所以G的祖宗里,只有D与C同一辈分的。然后就会一直向上调用D
  • 所以G的super.a会调用E的a方法,打印"E"。
  • 然后E的super.a()会调用D的a方法,打印"D"。
  • D与 C是同一辈分(同样是A的下一代),所以此时D的super.a()就继续按照从右往左规则执行,调用的是C的a方法,打印"C"。

G这边就执行完了。

(8)C已经是最左边的了,super调用开始向C的继承链上调用,C的super.a调用C的父亲(A)的a方法,打印"A"。
 

至此,调用son的a方法执行完闭。

 

上述步骤中,只要过程中有一个缺少super调用的,那么就不会继续执行下去。

 

总结

super动态绑定规则:
(1)从右往左执行,

如果左边的trait辈分小于等于当前的trait,那么super调用左边的这个trait。

如果在左边的trait辈分比当前的trait大,那将会从当前trait的继承链中往上调用,直到调用到的祖宗与左边trait辈分一样

(2)然后继续从右往左执行,即继续调用左边的trait。

(3)如果当前调用的trait已经是最左边的trait,且此时还有super调用,那么就会往当前trait的继承链中往上调用,直到没有super调用为止。
(4)上述三步中,只要过程中有一个缺少super调用的,那么就不会继续执行下去。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值