您现在的位置是:首页 >技术教程 >Scala学习(七)---面向对象特质网站首页技术教程
Scala学习(七)---面向对象特质
1.面向对象特质(Trait)
在Scala语言中,采用特质trait(特征)来代替接口的概念,也就是说,多个类具有相同的特质的时候,就可以将这个特质独立出来,采用关键字trait声明。
Scala中的trait可以拥有抽象属性和方法,也可以拥有具体的属性和方法,一个类可以混入多个特质(trait),这种感觉相对于Java的抽象类
Scala引入trait特征,第一用来替代Java的接口,第二也就是对单继承机制的一种补充。
2.特质声明
一个类具有某种特质,就意味着这个类满足了这个特质的所有要素,所以在使用的时候,也采用了extends关键字,如果有多个特制或者存在父类,那么需要采用with关键字进行连接。
基本语法:
没有父类:class 类名 extends 特质1 with 特质2 with 特质3…
有父类:class 类名 extends 父类 with 特质1 with 特质2 …
class TestTrait {
}
object TestTrait
{
def main(args: Array[String]): Unit = {
}
}
//定义一个特质
trait Age09{
//抽象的属性和方法
val age:Int
def sayHi():Unit
//具体的属性和方法
val age1:Int=10
def sayHi1():Unit=println("hi age")
}
trait young09{
}
class Father01{
}
//实现特质
//有父类的情况
class Children01 extends Father01 with Age09 with young09 {
override val age: Int = 21
override def sayHi(): Unit = "hello"
}
//没有父类的情况
class Children02 extends Age09 with young09 {
override val age: Int = 18
override def sayHi(): Unit = "hello "
}
2.1 特质的特点
a.特质可以同时拥有抽象方法和具体方法
b.动态混入:可灵活的扩展类的功能
c.动态混入:创建对象的时候混入trait,而无需使类混入该特质
d.如果混入的trait有未实现的方法,则需要实现
2.2 特质冲突
当一个类继承的父类和特质有同样的具体属性或者方法时候,调用此属性或者方法时,会报错,此时需要重写属性或者方法来解决冲突。如果属性使用var来修饰,则冲突就无法解决,因为在scala中var修饰的属性不可以重写。
object TestTrait02{
def main(args: Array[String]): Unit = {
val child0 = new Child03
println(child0.age)
}
}
trait TraitDemo1{
val age:Int=11
}
//父类
class Father03{
val age:Int=12
}
//子类
class Child03 extends Father03 with TraitDemo1 {
}
2.3 特质叠加
sub类混入的两个特质TraitA和TraitB,而这两个特质又同时继承了TraitC特质,此种情况称为特质的叠加。
class TestTrait03 {
}
object TestTrait03{
def main(args: Array[String]): Unit = {
val sub0 = new sub
println(sub0.info())
}
}
trait TraitC{
val age:Int
def info():String={
"age"
}
}
trait TraitB extends TraitC {
override val age:Int=12
override def info():String={
"young"+super.info()
}
}
trait TraitA extends TraitC {
override val age:Int=62
override def info(): String = {
"old" + super.info()
}
}
class sub extends TraitB with TraitA {
override def info():String="person is"+super.info()
}
可以看到,当一个类中混入多个特质的时候,scala会对所有的特质及其父特质进行一定的顺序进行排序,在上述例子中的顺序为TraitA–>TraitB–>TraitC,这相当于类在混入特质的顺序的倒序class sub extends TraitB with TraitA
如果想要调用某个指定的混入特质的方法,可以使用super[].方法来实现
super[TraitB].info()
2.4 特质自身类型
当一个类混入一个特质的时候,必须要混入这个特质依赖的另一个特质
语法:_:特质=>
trait Age1{
}
trait Young1{
_:Age1=>
}
class Person10 extends Young1 with Age1 {
}
2.5 特质和抽象类的区别
优先使用特质,一个类扩展多个特质是很方便的,但是只能扩展一个抽象类
如果需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行
扩展
1.obj.isInstanceOf[T] //判断obj是不是T类型
2.obj.asInstanceOf[T] //将obj强转为T类型
3.classOf获取类模板 //相当于Java中的反射