scala outline
trait作用及代码演示
trait作用
- Scala语言中,采用特质trait(特征)来代替java中接口的概念
- 特质是对scala中只允许单继承机制的一种补充
trait 代码演示
体会用trait实现以下功能
基本语法
trait 特质名 {
代码主体
}
没有父类:class 类名 extends 特质1 with 特质2 with 特质3 …
有父类:class 类名 extends 父类 with 特质1 with 特质2 with 特质3…
object Test {
def main(args: Array[String]): Unit = {
val c = new C()
val e = new E()
c.getConnect() // 链接oracle数据库
e.getConnect() // 链接mysql数据库
}
}
trait Trait01 {
//定义一个规范
def getConnect(): Unit
}
class A {}
class B extends A {}
// 如果一个类在混入特质和继承父类时,应当把父类写在extends后
class C extends A with Trait01 {
override def getConnect(): Unit = {
println("链接oracle数据库...")
}
}
class D {}
class F extends D {}
class E extends D with Trait01 {
override def getConnect(): Unit = {
println("链接mysql数据库...")
}
}
注意事项
- 特质可以同时拥有抽象方法和具体方法,即非抽象方法
- 一个类可以混入多个特质
- 所有的Java接口都可以当做Scala特质使用
trait 动态混入
作用:
可灵活的扩展类的功能
object Test {
def main(args: Array[String]): Unit = {
val gir: Person = new Person
// 男人,需要购买保健品重振雄风,女人却不需要,所以单独为男人混入该特质,即动态混入特质
// 必须要加返回值类型 Person with C,不然boy对象不可以调用buy这个方法
val boy: Person = new Person with C {
override def buy(): Unit = {
println("男人专享:购买六味地黄丸,重振雄风")
}
}
}
}
// 定义跑步行为
trait A {
def run(): Unit
}
// 定义讲话行为
trait B {
def speak(): Unit
}
// 定义购买保健品行为
trait C {
def buy(): Unit
}
// 我们知道,人可以跑步,讲话,所以可以混入特质A、B,但是男人,需要购买保健品重振雄风,女人却不需要,所以不必混入特质C
class Person extends A with B {
override def run(): Unit = {
println("慢悠悠的跑步")
}
override def speak(): Unit = {
println("小心翼翼的讲情话")
}
}
特质冲突
- 一个类混入多个特质,多个特质之间有
相同的抽象方法
,特质之间没有关系,直接对抽象方法实现一次即可
object Test {
def main(args: Array[String]): Unit = {
val c: C = new C
c.f()
}
}
trait A {
// 抽象方法
def f(): Unit
}
trait B {
def f(): Unit
}
class C extends A with B {
override def f(): Unit = {
println("特质A、B的f方法,我谁都不用。我只把你们的方法重写,用我自己的")
}
}
- 一个类混入多个特质,多个特质之间有
相同的非抽象方法
,特质之间没有关系,应该对相同的非抽象方法进行重写
object Test {
def main(args: Array[String]): Unit = {
val c: C = new C
c.f()
}
}
// 非抽象方法
trait A {
def f(): Unit={
println("特质A")
}
}
trait B {
def f(): Unit={
println("特质B")
}
}
class C extends A with B {
override def f(): Unit = {
println("特质A、B的f方法,我谁都不用。我只把你们的方法重写,用我自己的")
}
}
特质叠加
什么是特质叠加问题
一个类(Sub)混入的两个trait(TraitA,TraitB)中具有相同的非抽象方法,且两个trait混入相同的trait(TraitC)即及所谓的“钻石问题”,解决这类冲突问题,Scala采用了特质叠加的策略
处理办法:
加super.方法
解决问题代码演示
object Test {
def main(args: Array[String]): Unit = {
val sub: Sub = new Sub
println(sub.f()) // 输出结果 我的操作是--->向mysql中向hdfs中插入数据
}
}
trait C {
def f(): String = {
"插入数据"
}
}
trait A extends C {
override def f(): String = {
"向mysql中" + super.f()
}
}
trait B extends C {
override def f(): String = {
"向hdfs中" + super.f()
}
}
class Sub extends B with A {
override def f(): String = {
"我的操作是--->" + super.f()
}
}
上述案例中的super.f()调用的是父trait中的方法吗?
当一个类混入多个特质的时候,scala会对所有的特质及其父特质按照一定的顺序进行排序,而此案例中的super.f()调用的实际上是排好序后的下一个特质中的f()方法。排序规则如下:
- 第一步:列出混入的第一个特质B的混入关系,作为临时叠加顺序
- 第二步:列出混入的第二个特质A的混入关系,并将该顺序叠加到临时顺序前边,已经出现的特质不再重复
- 将子类Sub放在临时叠加顺序的第一个,得到最终的叠加顺序