您现在的位置是:首页 >技术教程 >Scala学习(七)---面向对象特质网站首页技术教程

Scala学习(七)---面向对象特质

肥大毛 2024-06-19 13:56:19
简介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中的反射
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。