説明
- Scala言語では、特性はインターフェースの概念を置き換えるために使用されます。つまり、複数のクラスが同じ特性を持っている場合、traitキーワードを使用して特性を分離して宣言できます。
- Scalaの特性には、抽象属性と抽象メソッドの両方、および非抽象属性と非抽象メソッドの両方が存在する可能性があります。
- クラスは複数の特性と混合できます。
単一の特性をブレンドする
object Scala03_Trait {
def main(args: Array[String]): Unit = {
val stu:PersonTrait03 = new Student03
stu.sleep()
stu.eat()
println(stu.name)
}
}
trait PersonTrait03 {
// 特质中既可以有抽象属性和抽象方法
var name: String
def sleep(): Unit
// 也可以有非抽象属性和非抽象方法
var age: Int = 18
def eat(): Unit = {
println("Person eat")
}
}
// 混入特质
class Student03 extends PersonTrait03 {
// 重写特质中的抽象方法和属性
override var name: String = "Li Ming"
override def sleep(): Unit = {
println("Student sleep")
}
}
複数の特性を混ぜる
- クラス継承なしで複数のトレイトを混合する:trait1をtrait2で拡張します…
- クラス継承が混在している複数のトレイトがあり、最初にクラスを継承し、次にトレイトをミックスします。ClassNameをtrait1とtrait2で拡張します…
- オブジェクトを作成するときは、特性を動的に混合します。新しいClassNameとtrait1 {抽象メソッドを上書き}。
object Scala04_Trait {
def main(args: Array[String]): Unit = {
/*val clzz = new MyClass04
clzz.mA()
val clazz1 = new MyClass004
clazz1.mB()*/
// 动态的混入特质
val clzz004 = new MyClass004 with TraitC {
override def mC(): Unit = {
println("mC")
}
}
clzz004.mC()
}
}
trait TraitA {
def mA(): Unit
}
trait TraitB {
def mB(): Unit
}
trait TraitC {
def mC(): Unit
}
class Super {
}
// 没有类继承的混入多个特质
class MyClass04 extends TraitA with TraitB with TraitC {
override def mA(): Unit = {
println("mA")
}
override def mB(): Unit = {
println("mB")
}
override def mC(): Unit = {
println("mC")
}
}
// 有继承,混入多个特质。继承的类放在第一个位置
class MyClass004 extends Super with TraitA with TraitB{
override def mA(): Unit = {
println("mA")
}
override def mB(): Unit = {
println("mB")
}
}
形質の対立(通常の対立)
- クラスが複数のトレイトと混在している場合、2つのトレイト間に関係がなくても、同じ名前の抽象メソッドがある場合は、抽象メソッドを書き直す必要があります。
- クラスが複数のトレイトと混在している場合、2つのトレイト間に関係がなくても、同じ名前の非抽象メソッドがある場合は、非抽象メソッドを書き直す必要があります。
object Scala05_Trait {
def main(args: Array[String]): Unit = {
val p = new Person05
p.m1()
val p2 = new Person005
p2.m1()
}
}
trait Person05TraitA {
def m1(): Unit
}
trait Person05TraitB {
def m1(): Unit
}
class Person05 extends Person05TraitA with Person05TraitB {
override def m1(): Unit = {
println("Person05中重写的m1方法")
}
}
trait Person005TraitA {
def m1(): Unit = {
println("Person005TraitA m1")
}
}
trait Person005TraitB {
def m1(): Unit = {
println("Person005TraitA m1")
}
}
class Person005 extends Person005TraitA with Person005TraitB {
override def m1(): Unit = {
println("Person005中重写的m1方法")
}
}
特性の積み重ね(ダイヤモンドの問題)
説明
トレイトAとトレイトBはトレイトCと混合されています。トレイトAとトレイトBはどちらも、トレイトCのm1メソッドを書き換えます。クラスは機能Aと機能Bを同時に混合します。次に、このクラスのm1メソッドはどのメソッドで実行されますか?これが菱形継承問題です。
コード
object Scala06_Trait {
def main(args: Array[String]): Unit = {
val operation = new MyOperation
println(operation.m1()) // 我的操作是:向HDFS向数据库插入数据
}
}
trait Operation {
def m1(): String = {
"插入数据"
}
}
trait DBOperation extends Operation {
override def m1(): String = {
"向数据库" + super.m1() }
}
trait HDFSOperation extends Operation {
override def m1(): String = {
"向HDFS" + super.m1()
}
}
class MyOperation extends DBOperation with HDFSOperation with Operation {
override def m1(): String = {
"我的操作是:" + super.m1()
}
}
実行結果分析
- 最初のステップ:一時的な順序として混合された最初の特性の継承関係をリストします。
DBOperation->操作 - ステップ2:2番目の特性の継承関係をリストし、最初の特性の順序の前に順序を重ね合わせます。すでに出現している特性は繰り返されないことに注意する必要があります。
HDFSOperation-> DBOperation->操作 - ステップ3:サブカテゴリを一時的なスタッキングシーケンスの最初に配置します。これが最後のスタッキングシーケンスです。
MyOperation-> HDFSOperation-> DBOperation-> Operation
注:この場合のスーパーは、その親特性オブジェクトを意味するのではなく、上記のスタックシーケンスの次の特性を意味します。