文章目录
- trait
- 1.定义trait
- 2.向类中混入特质
- 2.1没有父类
- 2.2有父类
- 3.动态混入
- 3.1动态混入查询功能到公司业务中
- 4.父类,子类,特质初始化优先级
- 5.Scala功能执行顺序
- 6.常用API
trait
–特质的学习需要类比Java中的接口,源码编译之后就是interface
–scala中没有接口的概念;
–scala可以将多个对象中相同的特征从对象剥离出来,形成一个独立的语法结构 => 特质trait
如果一个对象符合这个特质,那么可以将特质混入到这个对象中
–目的:增加约束,功能补充和叠加
–如果混入多个相同的特质,为避免出现钻石问题,需要定义一个执行的顺序
1.定义trait
trait Run{
def run():Unit
}
特质中的方法是抽象方法(模板)
2.向类中混入特质
–如果有父类,采用with
–如果没有父类,采用extends
–混入多个特质,第一个用extends其余都用with
2.1没有父类
class Cat extends Run {
override def run(): Unit = println("Cat run")
}
2.2有父类
class Stu extends person with Run {
override def run(): Unit = println("Stu run")
}
class person{}
–混入特质需要重写特质的所有抽象方法
–scala中抽象方法不需要定义,没有方法体就是抽象方法,抽象类需要加abstract
–学习时候要类比Java接口,但是特质可以继承类,接口不行
3.动态混入
–引入目的:方便程序开发OCP原则;
–开发程序代码:空难扩展开放OPEN,功能修改关闭CLOSE
–注意:OCP原则不要拿父类继承来 做OCP原则,原因是父类继承,是一种模板思想,而非程序OCP思想
–OCP原则最佳使用trait,在构建对象的时候,将新的功能混入到对象中
3.1动态混入查询功能到公司业务中
// 3.trait动态混入 也就是构建对象的时候用with进行功能混入;
class Accompany{
val user = new User() with select
user.selectUser()
}
trait select{
def selectUser(): Unit = {
println("select * from emp_user")
}
}
小结:动态混入也就是构建对象的时候直接使用with混入特质
4.父类,子类,特质初始化优先级
trait > current class
parent > trait > current class
多个特质情况下,从左到右依次执行
left trait > right trait
5.Scala功能执行顺序
–类混入特质也存在钻石问题,但是scala采用了一种特殊的方式–功能叠加
–如果混入多个相同的特质,为避免出现钻石问题,需要定义一个执行的顺序
“此处的执行顺序就是初始化顺序的反向操作”
执行顺序跳级到xxx
前提需要有继承关系
super[xxx].operateDate() 跳级执行操作
trait Operate {
def operatedata(): Unit = {
println("处理数据")
}
}
trait Database extends Operate {
override def operatedata(): Unit = {
print("Database")
super.operatedata() //整体意思就是Database处理数据
}
}
trait Log extends Operate {
override def operatedata(): Unit = {
print("Log ")
//此处的super表示上一级的super 此处上一级为DataBase,原因是功能一层一层包 特质中,重写的方法中使用super表示上一级
super.operatedata()
}
}
//上述所示,Database和Log两个都继承自Operate; MySQL同时继承自Databse和Log
class MySQL extends Database with Log { //Log Database处理数据 结果没有意义
//实例化MySQL对象,后 父类 特质等方法直接可以调用,不需要重写
}
//Log Database处理数据
图解如下
注意要点:
1.特质就是扩展功能,一级一级的扩展;
2.即便是特质的扩展也是优先初始化父类;
3.初始化完成后调用的时候是由外向内一层一层调用;
4.可以进行跳级调用 super[xxx].operaterData();
6.常用API
// 判断对象是否是某个类的实例
println(mysql.isInstanceOf[Operate]) //true
// 将对象转化为某个类的实例
val value1 = mysql.asInstanceOf[Object]
println(value1) //_18Scala面向对象编程trait.Demo02$MySQL@19bb089b
// 获取类的信息
val value = classOf[Operate]
println(value) //interface _18Scala面向对象编程trait.Demo02$Operate
Scala中
双等号 表示非空equals
equals 表示比较内存
但是一般情况下,比较对象,都是重写equals方法,完成自定义的比较功能