特质trait

在scala中是没有接口的概念的,但是有着和接口类似的概念,那就是特质trait。scala类和java一样,不允许多重继承。但是和java接口一样,可以实现任意多个特质。和java接口不一样的地方是,scala特质可以提供方法和字段的实现,相当于特质可以同时有用抽象方法和具体方法。一个简单的特质例子如下:

1
2
3
4
5
6
7
8
trait Drinker {
def eat(food : String) // 特质方法没有实体默认为抽象
}

class Animal extends Drinker { // extends关键字def eat(food : String): Unit = { // 不需要override
println("animal eat food:" + food)
}
}

如果一个类要继承多个特质,其他特质可以通过with关键字添加,比如:

1
2
3
4
5
6
7
8
trait Drinker {
def eat(food : String)
}

class Animal extends Drinker with Cloneable with Serializable { // with关键字def eat(food : String): Unit = {
println("animal eat food:" + food)
}
}

特质也采用了extends关键字,如果有多个特质存在父类,那么需要采用with关键字连接

1
2
3
4
1.没有父类
class 类名 extends 特质1 with 特质2 with 特质3 ...
2.有父类
class 类名 extends 父类 with 特质1 with 特质2

特质的具体实现

  1. scala特质和java接口不一样的地方是scala的特质可以实现内部的方法,而且继承该特质的类可以使用该方法的实现。
  2. 如果继承的类要重写该特质的方法,需要override关键字。
  3. 经常特质中可以有很多具体的实现,这些实现可以依赖特质的抽象方法

特质中的字段

  1. 特质中也可以定义字段,该字段可以是抽象的,也可以是具体的(即给出了初始值)。
  2. 特质中的字段被继承时,会加到子类当中,属于子类的一部分
  3. 特质中未初始化的字段在子类当中必须被重写

当一个trait有抽象方法和非抽象方法时
1.一个trait在底层对应两个trait.class接口
2.还对应 trait$class.class trait$class.class 抽象类

动态混入

带有特质的对象,动态混入

  1. 除了可以在类声明时继承特质以外,还可以在构建对象时混入特质,拓展目标类的功能
  2. 此种方式也可以应用于对抽象类功能进行拓展
  3. 动态混入时Scala特有的方式(Java没有动态混入),可以在不修改类声明/定义的情况下,拓展类的功能,非常的灵活,耦合性低
  4. 动态混入可以在不影响原有的继承关系上,给指定的类拓展功能

使用方法

使用 with方法进行连接 例如 with trait类名

如果抽象类中有抽象方法如何混入呢?我们可以在进行对象实例化的时候把实现放在后面 把 with trait类放在实现的前面 示例:

1
2
3
4
5
new MySQL3_ with Operate3 {
override def sayHi(): Unit = {
//sayhello的实现
}
}

Scala创建对象有几种方式

  1. new 对象
  2. apply创建
  3. 匿名子类方式
  4. 动态混入