Scala_Scala语法=》Scala 特质

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010003835/article/details/85239237

参考文档

Scala 特质全面解析

https://www.cnblogs.com/nowgood/p/scalatrait.html

Scala 中没有接口这样的概念,但是Scala 中有一种特殊类型的类,我们称其为特质。特质具有Java接口所具有的特性,除此之外,还具有一些Java接口不具备的特质。下面请跟随本篇文章踏入 Scala 特质的学习。

1.什么是Scala特质

2.特质的基本语法  

3.特质的构造顺序

4.混入特质的语法

5.混入特质的执行顺序

6.限制特质的使用场景

1.什么是Scala特质

  Scala 中不存在多继承,Scala 中只有单继承的方式。但是Scala 跟Java一样,可以通过混入多个接口达到近似的功能。

Scala的特质主要有以下几个特点

.1 Scala 中的特质主要用来定义接口,Scala 中的接定义与Java类似。

  def CC: String

  def QC(name: String): Unit

.2 除了基础的定义接口外,Scala 中的特质也允许存在非接口函数,这个特性跟Java8的扩展比较相似

.3 通过继承关系,限制特质的使用范围

.4 限制Scala 中的特质范围

1)限制特质只用于指定类型的子类

2)保证特质只能被添加到一个特定方法的类型,(实现该特制的类,必须具有某种结构 (如是否具有某个方法)) 

2.特质的基本语法  

Trait中方法定义

scala 的特质主要使用 trait 进行定义。

定义的方式如下:

trait TestTrait {

  def CC: String

  def QC(name: String): Unit

}

CC 方法:不接受任何参数,返回值为String

QC 方法:方法接受一个name 参数,无返回值

实现方法:

class XXC extends TestTrait {

  override def CC: String = "ccc"

  override def QC(name: String): Unit = println(s"${name}")
}

Trait中字段定义

如果在特质中定义字段,

必须在继承的具体类中实现(不需要 override 关键字),除了继承类为 abstract class (抽象类),不需要实现。

trait TestTrait2 {

  var userName: String

  val password: String

}


abstract class Trait2Imp extends TestTrait2 {

  var userName: String = "username"

}

带有具体方法的特质

scala 中的特质可以有具体的方法,示例如下

package traitCode

/**
  * Created by szh on 2018/12/25.
  */
trait TestTrait3 {

  def impMethod: String = {
    "this is a method"
  }

  def queryCC: Unit
}


class Trait3Imp extends TestTrait3 {

  override def queryCC: Unit = {
    println("ccccc")
  }

}

object Trait3ImpObj extends App {

  val d = new Trait3Imp()

  d.queryCC
  println(d.impMethod)

}

但是,需要注意

让特质混有具体行为有一个弊端. 当特质改变时, 所有混入该特质的类都必须重新编译.

3.特质的构造顺序

特质也可以有构造器,由字段的初始化和其他特质体中的语句构成。这些语句在任何混入该特质的对象在构造时都会被执行。
构造器的执行顺序:

  1. 调用超类的构造器;
  2. 特质构造器在超类构造器之后、类构造器之前执行;
  3. 特质由左到右被构造;
  4. 每个特质当中,父特质先被构造;
  5. 如果多个特质共有一个父特质,父特质不会被重复构造
  6. 所有特质被构造完毕,子类被构造。

4.混入特质的基本语法

混入特质有2个时机

1.类声明/实现 的阶段

2.声明实例的阶段

特质定义:

trait MultiTrait {

  def Multi1(name: String): Unit
}

trait MultiTrait2 {

  def Multi2(name: String): Unit
}


trait MultiTrait3 {

  def Multi3(name: String): Unit
}

1.类声明/实现 的阶段

class ImpMultiTrait extends MultiTrait with MultiTrait2{

  override def Multi1(name: String): Unit = {
    println(s"multi1 ${name}")
  }

  override def Multi2(name: String): Unit = {
    println(s"mulit2 ${name}")
  }
}

2.声明实例的阶段

 val f = new ImpMultiTrait with MultiTrait3 {
    override def Multi3(name: String): Unit = println("++++++")
  }
  f.Multi3("cccc")

特别注意 : 

整体代码

package traitCode

/**
  * Created by szh on 2018/12/25.
  */
trait MultiTrait {

  def Multi1(name: String): Unit
}

trait MultiTrait2 {

  def Multi2(name: String): Unit
}


trait MultiTrait3 {

  def Multi3(name: String): Unit
}

class ImpMultiTrait extends MultiTrait with MultiTrait2{

  override def Multi1(name: String): Unit = {
    println(s"multi1 ${name}")
  }

  override def Multi2(name: String): Unit = {
    println(s"mulit2 ${name}")
  }
}

object ImpMultiTraitMain extends App{

  val d = new ImpMultiTrait()

  d.Multi1("hahaha")

  d.Multi2("hahaha")

  val f = new ImpMultiTrait with MultiTrait3 {
    override def Multi3(name: String): Unit = println("++++++")
  }
  f.Multi3("cccc")

}

 

5.混入特质的执行顺序问题

特质可以将对象原本没有的方法与字段加入对象中
如果特质和对象改写了同一超类的方法, 则排在右边的先被执行.

abstract class Feline {
  def say()
}

trait Tiger extends Feline {
  // 在特质中重写抽象方法, 需要在方法前添加 abstract override 2个关键字
  abstract override def say() = println("嗷嗷嗷")
  def king() = println("I'm king of here")
}

class Cat extends Feline {
  override def say() = println("喵喵喵")
}

object Test extends App {
  val feline = new Cat with Tiger
  feline.say  // Cat 和 Tiger 都与 say 方法, 调用时从右往左调用, 是 Tiger 在叫
  feline.king // 可以看到即使没有 cat 中没有 king 方法, Tiger 特质也能将自己的方法混入 Cat 中
}

输出:

嗷嗷嗷
I'm king of here

 

6.限制特质的使用场景

我们可以限制特质的使用

主要分为以下两种类型

1.通过继承关系限制

2.通过结构化进行限制

  i.限制继承结构

  ii.限制方法结构

1.通过继承关系限制

此种方法较少使用,

主要语法如下:

trait [TraitName] extends [SuperThing]

含义如下:

此 TraitName 只可以被混入到继承了SuperThing的类中,这个SuperThing可以是特质,类或者抽象类。

示例

trait TQTrait extends SuperThing {

  def Fun1: Unit
}


class WF extends MultiTrait with TQTrait{

  override def Fun1: Unit = {
    println("WCG")
  }

  override def Multi1(name: String): Unit = println("name")
}

object WF extends App{
  val f = new WF
  f.Fun1
}

Error:(12, 34) illegal inheritance; superclass Object
 is not a subclass of the superclass SuperThing
 of the mixin trait TQTrait
class WF extends MultiTrait with TQTrait{

2.通过结构化进行限制

 

这个方案主要用到了自身类型(Self Type),Scala 中对于自身类型的描述如下:

任何具体类混入特质的时候,必须保证他的类型和特质的自身类型一致。

  i.限制继承结构

为了让特质必须继承 一个类 或者 该类的子类,我们可以进行如下的定义。


trait LimitTrait1 {

  this : SuperThing =>

  def betterThing

}

以上定义表示,LimitTrait 的实现类,必须继承自 SuperThing。

完整代码:

package traitCode

/**
  * Created by szh on 2018/12/25.
  */
trait LimitTrait1 {

  this : SuperThing =>

  def betterThing

}

class PrintOff extends LimitTrait1 {

  override def betterThing: Unit = {
    println("Just do better")
  }
}

object LimitTraitMain extends App {

  val c = new PrintOff
  c.betterThing
}

出错:

 

 

 

ii.限制方法结构

此种方法主要用于限制继承接口的类必须含有某种方法。

示例如下:

trait LimitTrait3 {

  this: {
    def speak: Unit
    def superMan: Unit
  } =>

}

完整代码:

package traitCode

/**
  * Created by szh on 2018/12/25.
  */
trait LimitTrait3 {

  this: {
    def speak: Unit
    def superMan: Unit
  } =>

}

class LimitTestMain extends LimitTrait3 {

  def speak: Unit = {
    println("zzzzzzzzzzzzzzzzzz")
  }

  def superMan: Unit = {
    println("yyyyyyyyyyyyyyyy")
  }

}

object LimitTestMain extends App{

  val f = new LimitTestMain

  f.speak

  f.superMan

}

如果不实现以上方法,会报错:

猜你喜欢

转载自blog.csdn.net/u010003835/article/details/85239237