一、为什么没有多重继承
c++允许多重继承
Java不允许多重继承,类只能继承一个超类,可以实现任意数量的接口。
如何继承这两个抽象基类?
Scala提供“特质”而非接口;特质可以同时抽象方法和具体方法。类可以实现多个特质。
二、当做接口使用的特质
trait Logger{
def log(msg: String)
}
class ConsoleLogger extends Logger{ //使用 extends 不能使用 implements
def log(msg: String): Unit ={ // 不需要使用override
println(msg)
}
}
三、带有具体实现的特质
trait Logger{
def log(msg: String){println(msg)}
}
class SavingAccount extends Logger{
def display(msg: String): Unit ={
log(msg)
}
}
val v = new SavingAccount()
v.display("Hello")
注:特质发生变化,所有混入特质的类都需要重新编译。
四、带有特质的对象
trait Logged{
def log(msg: String){} //特质,方法是个空实现
}
trait ConsoleLogger extends Logged{
override def log(msg: String) {println(msg)}
}
class SavingAccount extends Logged{ //类继承特质,方法的实现结果为空
def display(msg:String){log(msg)
}
}
val s = new SavingAccount() //构造对象,结果为空
s.display("Hello")
val s1 = new SavingAccount() with ConsoleLogger //在构造对象的时候,加入特质,结果为 Hello
s1.display("Hello")
五、叠加在一起的特质
trait Logged{
def log(msg: String){}
}
trait ConsoleLogger extends Logged{
override def log(msg: String) {println(msg)}
}
trait TimestampLogger extends Logged{
override def log(msg: String){
super.log(new java.util.Date() + " " + msg)
}
}
trait ShortLogger extends Logged{
val maxLength = 15
override def log(msg: String){
super.log(
if(msg.length <= maxLength) msg else msg.substring(0, maxLength-3) + "..."
)
}
}
class SavingAccount extends Logged {
def display(msg: String) {
log(msg)
}
}
val s = new SavingAccount with ConsoleLogger with TimestampLogger with ShortLogger //ShortLogger的log方法先执行,然后是 TimestampLogger
s.display("Hello")
val s1 = new SavingAccount with ConsoleLogger with ShortLogger with TimestampLogger //TimeStampLogger的方法先执行,然后是 ShortLogger
s1.display("Hello")
结果:
Wed Aug 31 23:27:53 CST 2016 Hello
Wed Aug 31 2...
六、在特质中重写抽象方法
trait Logged{
def log(msg: String)
}
trait ConsoleLogger extends Logged{
override def log(msg: String) {println(msg)}
}
trait TimestampLogger extends Logged{
abstract override def log(msg: String){ //继承抽象方法,需要使用abstract关键字,对抽象方法进行重写
super.log(new java.util.Date() + " " + msg)
}
}
class SavingAccount extends ConsoleLogger {
def display(msg: String) {
log(msg)
}
}
val s = new SavingAccount with TimestampLogger
s.display("Hello")
结果:
Wed Aug 31 23:51:40 CST 2016 Hello
七、当做富接口使用的特质
trait Logged{ // 特质将抽象方法,和具体方法结合在一起
def log(msg: String)
def info(msg: String){log(msg)}
def warn(msg: String){log(msg)}
}
trait ConsoleLogger extends Logged{
override def log(msg: String) {println(msg)}
}
trait TimestampLogger extends Logged{
abstract override def log(msg: String){ //继承抽象方法,需要使用abstract关键字,对抽象方法进行重写
super.log(new java.util.Date() + " " + msg)
}
}
class SavingAccount extends ConsoleLogger {
def display(msg: String) {
info(msg)
}
}
val s = new SavingAccount with TimestampLogger
s.display("Hello")
结果:
Thu Sep 01 09:38:54 CST 2016 Hello
八、特质中的具体字段
在子类中添加特质,特质中的字段就相当于子类中的字段
九、特质中的抽象字段
特质中的抽象字段,在子类的具体实现中必须要被重写