美文网首页
scala ===trait 多继承的diamond问题

scala ===trait 多继承的diamond问题

作者: sadamu0912 | 来源:发表于2019-06-01 09:10 被阅读0次

    trait类似于java中的interface.可以在类和对象上,扩展其特性,包括对象的属性还有行为。但是特质不能被实例化,因此特质没有参数。
    在class或者object继承多个trait的时候,有可能出现diamond问题。如下图:


    image.png

    上图中的代码如图所示:

    trait Animal {
      def talk: String
    }
    trait Cat extends Animal {
     override def talk: String = "I am Cat"
    
      def hello:Unit={
        println("hello")
      }
    }
    trait Dog extends Animal {
       def talk: String = "I am Dog"
    }
    trait Monkey extends Animal {
      def talk: String = " i am a monkey"
    }
    
    object TestTrait extends Dog  with Cat with Monkey {
      def main(args: Array[String]): Unit = {
          println(this.talk)
      }
    }
    

    但是很不幸,上面的代码编译会报错。
    为什么报错,首先我们先来看trait继承的时候的linerization.红色的箭头,就是trait线性化之后的trait 叠加流向。 TestTrait ==》Monkey ==》Cat ===》Dog==>Animal

    然后我们来看,后面几个特性都具有的方法 talk .Monkey是没有override的,然后Cat是有override 的,然后Dog是没有override的。那么TestTrait对talk方法到底重写不重写呢。
    编译器就不会通过。对于特性的方法,要么只有一个没有override的talk方法,因为只有一个,所以他肯定调用这个talk方法。要么前面有很多个talk方法。后面有大于等于1个连续的override。最后override掉方法。我有一个比较好方法去理解这个。就像叠立方型的木块。在trait linerization 链条中。第一个设一个固定的面积值。比如6 。假如后面没有override.那么面积小了,比如说5.。那我们能看见两个木块,到底选哪个呢。编译器也不知道。假如有override ,面积大了,比如说7 ,就会覆盖掉前面的,只能看到最上面的那个方法,假如这个时候又来一个方法没有override,又变小了,那又是可以看见两个方块。所以编译器又困惑了。
    总而言之,就是在trait linerization 链条中,Monkey ==》Cat ===》Dog==>Animal,两种情况。
    1 只有一个没有override的方法
    2 大于等于1个没有override,并且连续,然后跟着若干个连续的override.
    所以上面的只要把Monkey的talk方法override掉。

    然后具体的如何线性化特性,请看这边文章

    相关文章

      网友评论

          本文标题:scala ===trait 多继承的diamond问题

          本文链接:https://www.haomeiwen.com/subject/dvcotctx.html