【图文详细 】Scala——特质 Trait

版权声明:版权声明:本文为博主原创文章,转载请附上博文链接! https://blog.csdn.net/qq_42246689/article/details/85146276

4、特质 Trait 

4.1、特质的定义 

Scala 和 Java 语言一样,采用了很强的限制策略,避免了多继承的问题。在 Java 语言中,只 允许继承一个超类,该类可以实现多个接口,但 Java 接口有其自身的局限性:接口中只能包括抽象方法,不能包含字段、具体方法。Scala 语言利用 trait 解决了该问题,在 Scala 的 trait 中,它不但可以包括抽象方法还可以包含字段和具体方法。

trait 的示例如下: 

package com.mazh.scala.day2.oop 
 
trait DAO{ 
  // 抽象字段
 
  val id:Int 
  // 具体 字段
 
  val name:String = "huangbo" 
// 带 实现的具体方法
 
  def delete(id:String):Boolean = true 
// 定义一个抽象方法,注意不需要加 abstract, 加了 abstract反而会报错
 
  def add(o:Any):Boolean 
  def update(o:Any):Int 
  def query(id:String):List[Any] 
}

4.2、Trait 的使用 

4.2.1、Trait 使用概述 

Java 中:

1、接口是一个特殊的抽象类

2、里面所有的方法都是抽象方法。 
 
Scala 中:

1、 特质里面的方法既可以实现,也可以不实现 那么跟抽象类有什么区别,两点原因:

    1、优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。

    2、如果你需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数, 而特质不行。例如,你不能说 trait t(i: Int) {},参数 i 是非法的。

2、抽象类,我们用的是 extends,我们只能单继承,但是我们可以多实现

3、实现特质,如果没有继承其它类,那么使用第一个特质使用 extends,后面的使用 with, 所以如果有考题说实现特质只能使用 with,这是不对的。 
 
Trait 的几种不同使用方式

    1、当做 Java 接口使用的 trait,全是抽象字段和抽象方法

    2、带实现方法的 trait

    3、带具体字段的 trait

Traits 的底层实现就是采用的 Java 的抽象类

4.2.1、将特质作为接口使用 

Scala 中的 Triat 是一种特殊的概念 

首先我们可以将 Trait 作为接口来使用,此时的 Triat 就与 Java 中的接口非常类似 

在 Triat 中可以定义抽象方法,就与抽象类中的抽象方法一样,不给出方法的具体实现 

在 Triat 中也可以定义具体方法,给出方法的具体实现 在 Triat 中可以定义具体字段,

也可以定义抽象字段 类可以使用 extends 关键字继承 trait,注意,这里不是 implement,而是 extends,

在 scala 中没有 implement 的概念,无论继承类还是 trait,统一都是 extends 类继承 trait 后,

必须实现其中的抽象方法,实现时不需要使用 override 关键字

scala 不支持对类进行多继承,但是支持多重继承 trait,使用 with 关键字即可 

trait MySQLDAO{ 
  val id:Int 
  def add(o:Any):Boolean 
  def update(o:Any):Int 
  def query(id:String):List[Any] 
} 
 
// 如果有多个 trait的话,则使用 with关键字即可 
class DaoImpl extends MySQLDAO with Serializable{ 
  // 给父类中的抽象字段赋值。
   override val id = 12 
  // 实现抽象方法
   def add(o:Any):Boolean = true 
  def update(o:Any):Int = 1 
  def query(id:String):List[Any] = List(1,2,3) 
}

4.2.2、在 Trait 中定义具体方法和属性 

trait MySQLDAO{ 
 
  val id:Int 
  val name:String = "huangbo" 
 
  def add(o:Any):Boolean 
  def update(o:Any):Int 
  def query(id:String):List[Any] 
  def delete(id:Int) = {println("delete one record")} 
} 
 
// 如果有多个 trait的话,则使用 with关键字即可 
class DaoImpl extends MySQLDAO with Serializable{ 
 
  // 实现父类中的抽象方法,必须的
  def add(o:Any):Boolean=true 
  def update(o:Any):Int= 1 
  def query(id:String):List[Any]=List(1,2,3) 
 
  // 给父类中的抽象字段赋值,必须的
   override val id = 12 
}

4.3.5、为实例对象混入 Trait 
有时我们可以在创建类的对象时,指定该对象混入某个 Trait,

这样,就只有这个对象混入该 Trait 的方法,而类的其他对象则没有 

package com.mazh.scala.day2.oop 
 
trait MyLogger { 
  def log(msg:String){} 
} 
trait Logger_A extends MyLogger{ 
  override def log(msg:String): Unit ={ 
    println("test:"+msg) 
  } 
} 
trait Logger_B extends MyLogger{ 
  override def log(msg:String): Unit ={ 
    println("log:"+msg) 
  } 
} 
class Person123(val name:String) extends Logger_A{ 
  def sayHello(): Unit ={ 
    println("Hi ,i'm name") 
    log("sayHello is invoked!") 
  } 
} 
object  MyLogger_Trait_Test{ 
  def main(args: Array[String]) { 
    val p1=new Person123("liudehua") 
    p1.sayHello() 
    val p2=new Person123("zhangxueyou") with Logger_B 
    p2.sayHello() 
  } 
} 

4.3.6、Trait 调用链 

Scala 中支持让类继承多个 Trait 后,依次调用多个 Trait 中的同一个方法,只要让多个 Trait 的同一个方法中,在最后都执行 super.方法 即可 类中调用多个 Trait 中都有的这个方法时,首先会从最右边的 Trait 的方法开始执行,然后依 次往左执行,形成一个调用链条 这种特性非常强大,其实就相当于设计模式中的责任链模式的一种具体实现依赖 

trait Handler { 
  def handler(data:String){} 
} 
trait Handler_A extends Handler{ 
  override def handler(data:String): Unit = { 
    println("Handler_A :"+data) 
    super.handler(data) 
  } 
} 
trait Handler_B extends Handler{ 
  override def handler(data:String): Unit = { 
    println("Handler_B :"+data) 
    super.handler(data) 
  } 
} 
trait Handler_C extends Handler{ 
  override def handler(data:String): Unit = { 
    println("Handler_C :"+data) 
 super.handler(data) 
  } 
} 
class  Person_TraitChain(val name:String) extends Handler_C with Handler_B with 
Handler_A{ 
  def sayHello={ 
    println("Hello "+name) 
    handler(name) 
  } 
} 
 
object TraitChain_Test{ 
  def main(args: Array[String]) { 
    val p=new Person_TraitChain("zhangxiaolong"); 
    p.sayHello 
  } 
} 

运行结果: 

Hello lixiaolong 
Handler_A :zhangxiaolong 
Handler_B :zhangxiaolong 
Handler_C :zhangxiaolong 

猜你喜欢

转载自blog.csdn.net/qq_42246689/article/details/85146276