要点:
类可以实现任意数量的特质
特质可以提供实现
当一个类实现多个特质的时候,顺序很重要 ——其方法需要被先执行的特质应该放在越后面
注意1: 因为scala中一个类可以实现多个特质,然而特质中的又可以提供实现,所以就存在了c++中多继承的问题,究竟是调用哪一个的问题。Scala中的解决办法是如果一个类扩展多个特质,并且有冲突的方法实现,那么扩展类必须重写该方法,你可以在扩展类中调用父类方法,这里被调用的父类是最后一个被扩展的(写在后面的)
注意2: scala中的特质扩展之所以会有顺序要求,主要是因为特质中的super.xxx (这里xxx表示方法名)并不是表示调用父类的xxx方法,而是表示调用扩展顺序中前一个特质的xxx方法
注意3 :由于特质也可以扩展类,所以出现了一个问题,即java中不允许的多继承问题,比如,我定义一个类继承了一个类并且扩展了一个特质(并且这个特质继承了另一个类),这样的结果是我继承了两个类,并且扩展了一个特质
这个问题的解决办法是,如果特质继承的类是我需要继承的类的父类就可以,scala这些东西使用中应该注意
整体来看,scala的特质既有java中接口的特性又有抽象类的特性(个人感觉特质在被编译成class的时候会根据内容来编译成接口或者抽象类)
特质中未被实现的方法默认为抽象方法,不用abstract 关键字
类中实现特质时使用extends关键字,多个特质时使用with关键字,多个特质时需要注意顺序
在Scala中会出现下面这样的代码,主要是想要打上自己的logo而已
这里的abstract 和 override 都是必须添加的
特质中可以有字段,如果被字段是被初始化了得,则会被编译装配到子类中,如果未被初始化,则为抽象字段,子类必须自己重写
特质不能有构造器参数,这样带来一个显而易见的问题是,如果特质构造器中使用到了它的抽象字段,由于在构造过程中先调用父类的构造器,这时由于未被初始化参数会抛出异常。
解决办法是下面一种看上去糟糕的写法,提前定义
classMylog extends{
Val fileName="myapp.log"
} withFileLogger{
}
还有一种办法是使用懒值,这种值会在第一次被调用时初始化,有时候很有用,不过由于懒值在每次使用前都需要检查是否初始化,所以并不高效
由于scala的这些特性,编译器承担了更大的压力,所以很慢(真的比java慢很多)