特质 trait
Scala中没有接口interface的概念
特质用于在类之间共享程序接口和字段,类似Java接口
特质是字段和方法的集合,可以提供字段和方法实现
类和单例对象都可以扩展特质extends
特质不能被实例化,因此没有构造参数,类似Java接口
特质使用trait关键字定义
实现特质中的方法使用override
import scala.collection.mutable.ArrayBuffer
trait Pet {
val name:String
def cry():Unit
}
class Dog(val name: String) extends Pet{
override def cry()=println("wow ...")
}
val dog = new Dog("Harry")
val animals = ArrayBuffer.empty[Pet]
animals.append(dog)
animals.foreach(pet => {println(pet.name);pet.cry()}) // Prints Harry wow ...
混入特质(mixin)
当某个特质被用于组合类时,被称为混入
一个类只能有一个父类但是可以有多个混入(分别使用关键字extends和with)
abstract class A {
val message: String
}
class B extends A {
val message = "I'm an instance of class B"
}
trait C extends A {
def loudMessage = message.toUpperCase()
}
//构造顺序由左往右,如果前面已经构造了某个父类,后面子类的该父类不会重复构造
class D extends B with C
val d = new D
println(d.message) // I'm an instance of class B
println(d.loudMessage) // I'M AN INSTANCE OF CLASS B
动态混入特质
class Drawing {
//this:Type=> 自身类型,表示该类实例化时必须混入相应特质或子特质,self是this的别名。
self: Shape =>
def start(): Unit = draw()
}
trait Shape {
def draw(): Unit
}
trait Square extends Shape {
def draw(): Unit = println("draw a square")
}
trait Triangle extends Shape {
def draw(): Unit = println("draw a triangle")
}
//动态混入
(new Drawing() with Square).start()
(new Drawing() with Triangle).start()
特质与抽象类的选择
1.优先使用特质
- 抽象类只能继承一次
- 特质可混入多个
2.需要使用带参构造方法时,使用抽象类
3.与Java互操作性
- 抽象类与Java完全可互操作
- 特质只有在不包含任何实现代码时才可互操作
课堂代码:
package oop
trait Type1 {
def wheel():String={"有四个轮子"}
def run():Unit
}
trait Type2{
def fly():Unit={println("可以飞")}
def downSea():Unit={println("可以下水")}
}
abstract class Car{
val seat=4
def brand():String
def engine():String
def didi():String={"汽车鸣笛:滴滴滴"}
}
class BMW extends Car with Type1 with Type2{
override def brand(): String = "德国宝马系"
override def engine(): String = "6.0自然吸气,燃油动力"
override def run(): Unit= println("在陆地上跑")
}
object DemoCar{
def main(args: Array[String]): Unit = {
val bmw=new BMW
bmw.run() //在陆地上跑
println(bmw.brand()+"\t"+bmw.engine()+
"\t座位数:"+bmw.seat) //德国宝马系 6.0自然吸气,燃油动力 座位数:4
}
}
定义一个新的类,继承Car
class Lingyun extends Car{
override def brand(): String = "凌云汽车"
override def engine(): String ="纯电动汽车"
}
创建实例对象:
def main(args: Array[String]): Unit = {
val lingyun:Lingyun with Type1 with Type2 =new Lingyun with Type1 with Type2{
override def run(): Unit = println("两个轮子的电动汽车")
//。。。此处可按需求重写方法
}
lingyun.run() //两个轮子的电动汽车
lingyun.fly() //可以飞
println(lingyun.brand()) //凌云汽车
println(lingyun.wheel()) //有四个轮子
}