10_Scala_OOP下_接口_特质
Java接口
interface 接口名 ; class 类名 implements 接口名1,接口2
在Java中 一个类可以实现多个接口。 接口之间支持多继承 接口中属性都是常量 接口中的方法都是抽象
Scala接口 特质trait 来代替接口的概念 trait = interface + abstract class
一个类具有某种特质,用extends关键字,如多个特质或存在父类,用with关键字连接
无父类: class 类名 extends trait1 with trait2
有父类: class 类名 extends 父类 with trait1 with trait2
特质是对继承的一种补充 Scala引入trait特征
1 替代Java的接口,
2 对单继承机制的一种补充(Scala是单继承)
特质trait
1 java接口都可以当做Scala特质使用
2 特质可以同时有:抽象方法和具体方法(富接口),一个类可以实现/继承多个特质
3 特质中没有实现的方法就是抽象方法 类通过extends继承特质,通过with可以继承多个特质
4 特质中的方法并不一定是抽象的,也可以有非抽象方法(即:实现了的方法)
object Trait_introduction {
def main(args: Array[String]): Unit = {
val a_mysql = new A_mysql
val b_mysql = new B_mysql
a_mysql.getConnect // A_mysql_connection
a_mysql.hiTrait() //hello Trait
b_mysql.getConnect //B_mysql_connection
b_mysql.hiTrait() // hello Trait
}}
// type Serializable = java.io.Serializable Java的接口都可以当做trait来使用
//1 java接口都可以当做Scala特质使用
object T1 extends Serializable { }
//2 特质可以同时有:抽象方法和具体方法 (富接口),一个类可以实现/继承多个特质
trait T_sql_connt { //特质
def hiTrait(): Unit ={println("hello Trait")}
def getConnect
}
abstract class AA { //父类
def get_AA
}
//3 特质中没有实现的方法就是抽象方法 类通过extends继承特质,通过with可以继承多个特质
//无父类 class 类名 extends trait1 with trait2
class A_mysql extends T_sql_connt{
override def getConnect: Unit = println("A_mysql_connection")
}
//有父类 class 类名 extends 父类 with trait1 with trait2
class B_mysql extends AA with T_sql_connt{
override def get_AA: Unit = println("get_AA_from B_mysql")
override def getConnect: Unit = println("B_mysql_connection")
}
特质的对象 - 动态混入 MixIn (OCP闭合原则,修改源码关闭,功能扩展开放)
1 继承特质以外,也构建对象时混入特质,扩展目标类的功能 (2 可以理解为:抽象类功能进行扩展)
3 不修改类声明/定义的情况下,扩展类的功能,灵活,解耦 。
4 不影响原有的继承关系的基础上,给指定的类扩展功能
object MixInTest1 {
def main(args: Array[String]): Unit = {
//不影响原有的继承关系的基础上,给指定的类扩展功能
//不修改类声明/定义的情况下,扩展类的功能,灵活,解耦
//构建对象时混入特质 with 特质
val a = new Mysql_A with Insert
a.insert(97)
val b0 = new Mysql_B {} // 抽象类实例化 {} 保留,理解为{}已经实现了抽象化(刚好mysql_B 没有方法需要实现)
val b = new Mysql_B with Insert // abstract class Mysql_B
b.insert(98)
// 抽象类有抽象方法,动态混入特质, 先with 特质,再去实现override
val c = new Mysql_C with Insert {
override def hello: Unit = println("hello")
}
c.insert(99)
}}
// 特质
trait Insert{
def insert(id: Int): Unit = { //已经实现
println("insert : " + id)
}}
class Mysql_A{ }
abstract class Mysql_B
abstract class Mysql_C{
def hello
}
特质的对象 -叠加特质
对象的混入多个特质 - 叠加特质,特质声明 从左到右,方法执行顺序 从右到左
Scala执行叠加对象的方法时,会首先从后面的特质(从右向左)开始执行 (如无super,直接是最右边的那个)
Scala中特质中如调用super,并不一定表示调用父特质的方法,而是向前面(左边)继续查找特质,如找不到,才会去父特质查找
指定:super[特质].xxx(…).其中的泛型必须是该特质的直接超类类型
object AddTraits2 {
def main(args: Array[String]): Unit = {
// 构建 从左到右
val msql_A_B = new Msql_Test with Op_Son_A with Op_Son_B
println(msql_A_B) //Grandfather Father Op_Son_A Op_Son_B
//方法 从右到左
// 调用对象方法时候,如无super,最右边既是 trait的实现方法,既是该对象的方法
val msql_A_C = new Msql_Test with Op_Son_A with Op_Son_C // "短路"
msql_A_C.op_update(300)
// 方法 从右到左
// 调用对象方法时候,super, 不一定是父类,优先左边
// Op_Son_A 的 super 调用 Op_Son_B , Op_son_B的super[Op_Father] 调用 Op_Father
val msql_C_B_A = new Msql_Test with Op_Son_C with Op_Son_B with Op_Son_A
msql_C_B_A.op_update(200) // Op_Son_A_update: 200 p_Son_B_update: 200 Op_father_update: 200
// 短路review //new Msql_Test with Op_Son_A with Op_Son_B
// Op_Son_B 自身的实现方法后, Op_son_B的super[Op_Father] 调用 Op_Father 而不会走到 Op_Son_A (如果是 super.op_update(id))
msql_A_B.op_update(100) //Op_Son_B_update: 100 Op_father_update: 100
println("##########")
// Op_Son_A 自身的实现方法后, Op_son_A的super.op_update(id) 调用 左边的 Op_Son_C
val msql_C_A = new Msql_Test with Op_Son_C with Op_Son_A
msql_C_A.op_update(500) //Op_Son_A_update: 500 Op_Son_C_update: 500
}}
trait Op_GrandFather {
println("Grandfather")
def op_update(id: Int)
}
trait Op_Father extends Op_GrandFather {
println("Father")
override def op_update(id: Int): Unit = {
println(" Op_father_update: " + id)}
}
trait Op_Son_A extends Op_Father {
println("Op_Son_A")
override def op_update(id: Int): Unit = {
println("Op_Son_A_update: " + id)
super.op_update(id)
}}
trait Op_Son_B extends Op_Father {
println("Op_Son_B")
override def op_update(id: Int): Unit = {
println("Op_Son_B_update: " + id)
super[Op_Father].op_update(id) //说明:super[?] ?的类型,必须是当前的特质的直接父特质(超类)
}}
trait Op_Son_C extends Op_Father {
println("Op_Son_C")
override def op_update(id: Int): Unit = {
println("Op_Son_C_update: " + id)
}}
class Msql_Test{}
特质的对象 重写抽象方法
abstract override该方法仍然是一个抽象方法(因为没有完全的实现,需要其它特质继续实现[通过混入顺序])
特质的对象 富接口使用的特质 (抽象方法,又有非抽象方法)
特质的对象 具体字段
初始化了 - 具体字段
未初始化 - 抽象字段。具体对象混入该特质的类就具有了该字段,非继承, 变成自己的字段 直接加入类
未被初始化的字段在具体的子类中必须被重写
object AddTrait_Abstract {
//没有方法的具体实现,编译不通过,可重写抽象方法,这样 就必须考虑动态混入的顺序问题
//某个方法增加了abstract override该方法仍然是一个抽象方法(因为没有完全的实现,需要其它特质继续实现[通过混入顺序])
def main(args: Array[String]): Unit = {
// TraitAbsAlex 的super.sayHello 找左边 TraitAbsBoB # 非父类
val alex = new Alex with TraitAbsBoB with TraitAbsAlex
//sayHello Alex
// sayHello BoB
alex.sayHello
// val alex1 = new Alex with TraitAbsAlex with TraitAbsBoB // 编译不过
// 6 特质的对象 具体字段
// 初始化了 - 具体字段
// 未初始化 - 抽象字段。具体对象混入该特质的类就具有了该字段,非继承, 变成自己的字段 直接加入类
//未被初始化的字段在具体的子类中必须被重写
val alex1 = new Alex with Trait_attr {
override var name: String = "alex_init" //未被初始化的字段在具体的子类中必须被重写
override def showInfo: Unit = println("this is alex")
}}}
trait Trait_Abs {
def sayHello
}
// abstract override该方法仍然是一个抽象方法 需要其它特质继续实现[通过 叠加特质 -> 方法混入顺序]
trait TraitAbsAlex extends Trait_Abs {
abstract override def sayHello: Unit = {
println("sayHello Alex")
super.sayHello
}}
trait TraitAbsBoB extends Trait_Abs {
override def sayHello: Unit = {
println("sayHello BoB")
}}
class Alex {}
//5 特质的对象 富接口使用的特质 (抽象/非抽象方法共存)
// 初始化了 - 具体字段
// 未初始化 - 抽象字段。具体对象混入该特质的类就具有了该字段,非继承, 变成自己的字段 直接加入类
trait Trait_attr {
def hello: Unit = println("hello")
var name: String
var age: Int = 20
def showInfo
}
特质的对象 -构造顺序
声明类同时混入特质时候 是一个整体, 如果声明类没有混入特质,而是在对象创建时候混入,构造顺序有差异
object MixinSel {
def main(args: Array[String]): Unit = {
//class Sumi extends Alex with Son_C with Son_D 是一个整体,在with Son_D 之前对象还未创建出来
//Alexx 1 调用当前类的超类构造器
//GrandFather_A 2 第一个特质的父特质构造器
//Father_B 2 第一个特质的父特质构造器
//Son_C 3 第一个特质构造器
//Son_D 4 第二个特质构造器
//Sumi 5 本类构造器
val sumi = new Sumi
// 动态混入 之前 Sully对象已经创建 class Sully extends Alexx & new Sully with Son_C with Son_D
// Alexx 1 调用当前类的超类构造器
//Sully 2 本类构造器
//GrandFather_A 3 第一个特质的父特质构造器
//Father_B 3 第一个特质的父特质构造器
//Son_C 4 第一个特质构造器
//Son_D 4 第一个特质构造器
val sully = new Sully with Son_C with Son_D
}}
trait GrandFather_A {println("GrandFather_A")
}
trait Father_B extends GrandFather_A {println("Father_B")
}
trait Son_C extends Father_B {println("Son_C ")
}
trait Son_D extends Father_B {println("Son_D")
}
class Alexx {println("Alexx")
}
class Sumi extends Alexx with Son_C with Son_D {
println("Sumi")
}
class Sully extends Alexx {
println("Sully")
}
特质的对象 -扩展类的特性
特质可以继承类,以用来拓展该类的一些功能
混入该特质的类,会自动成为该特质所继承的超类的子类
如果混入该特质的类,继承了一个父类(A),则要求A是特质超类的子类(避免多继承现象)
特质的对象 -自身类型(目的:解决特质的循环依赖问题) 限制混入该特质的类的类型,要求混入的类必须是超类的子类
//特质可以继承类,以用来拓展该类的一些功能
trait MapException extends Exception{
def map: Unit = {
println(getMessage()) //getMessage()来自于Exception
}
}
//混入该特质的类,会自动成为该特质所继承的超类的子类
class AlexMapException extends MapException{
override def getMessage: String = "已经是Exception子类,可以重写getMessage方法"
}
//如果混入该特质的类,继承了一个父类(A),则要求A是特质超类的子类(避免多继承现象)
class AlexRedcuceException extends IndexOutOfBoundsException with MapException{ // 特质超类是exception
override def getMessage: String = "IndexOutOfBoundsException 是 Exception子类"
}
class ALEX_TEST{}
// ALEX_TEST 不是Exception 子类
//illegal inheritance; superclass ALEX_TEST is not a subclass of the superclass Exception
class AlexRedcuceException2 extends ALEX_TEST with MapException{
override def getMessage: String = "IndexOutOfBoundsException 是 Exception子类"
}
// Logger就是自身类型特质, 自身类型后 要求混入该特质的类也是 Exception子类
// trait Logger { this: Exception => 等价于 trait Logger extends Exception,
trait Logger {
// 明确告诉编译器,我就是Exception,如果没有这句话,下面的getMessage不能调用
this: Exception =>
def log(): Unit ={
// 既然我就是Exception, 那么就可以调用其中的方法
println(getMessage)
}}
//class bob extends Logger {} //报错 要求bob 必须是exception子类
//class alice extends Exception with Logger {} // alice 可以混入logger 因为alice 是 exception子类
补充
//当一个类继承了一个trait 那么该类的实例,就可以传递给这个trait引用
trait MyTrait01 {}
class A extends MyTrait01 {}
object B {
def test(m: MyTrait01): Unit = {
println("b ok..")
}
}
val a01 = new A
B.test(a01)
- 点赞
- 收藏
- 关注作者
评论(0)