scala基础之特质trait

Scala中,trait相当于Java中的接口,遇到需要使用Java接口的场景时,你就在Scala中可以使用trait了。

 

我们知道Java中你可以实现多个接口,那么Scala中,你也可以继承多个trait

 

Java中接口不能有自己的实现方法,但是Scala中trait可以包含自己的实现方法

 

一 特质用作接口

接口的作用:对行为进行规范,具有解耦的作用,满足业务系统依赖倒置的设计原则

注意:

第一:如果只需要一个那么使用extends,要实现多个trait,需要使用with

第二:抽象类继承trait,可以不给具体的实现,实现可以交给子类去做

 

trait BaseSoundPlayer {
    def play(music:String)
    def close
   
def puase(music:String,time:Int)
    def stop
   
def resume
}

trait BaseVedioPlayer {
    def display(vedio:String)
}
class MP4SoundPlayer extends BaseSoundPlayer with BaseVedioPlayer{
    override def play(music: String): Unit = {
        println("playing music "+music)
    }

    override def stop: Unit = {
        println("stop to play")
    }

    override def puase(music: String, time: Int): Unit = {
        println("pause to play music "+music+" for "+time+" s")
    }

    override def close: Unit = {
        println("closed  player")
    }

    override def resume: Unit = {
        println("resume to play")
    }

    override def display(vedio: String): Unit = {
        println("this player also watch the vedio "+vedio)
    }
}
 
 
abstract class BasePlayer extends BaseSoundPlayer with BaseVedioPlayer{

}
 

二 使用特制中的抽象字段和实际子段

在特质中定义抽象字段和实际子段,以便于继承该特质的类都可以使用这些字段

 

声明一个变量,赋一个初始值,就是一个实际字段,否则这个字段就是抽象字段

注意:

# 抽象字段不需要加override,而且变量修饰符应该和trait一样,因为trait不会针对抽象字段产生get set方法,所以子类就需要提供变量修饰符

# 实际字段如果是var变量,不需要加override关键字,那么子类重写不需要加变量修饰符,因为本身这个字段就有set方法,所以可以子类就可以直接修改

# 实际子段如果是val变量,需要加override关键字,那么子类重写必须加上变量修饰符,因为trait中的该字段没有set方法,如果你想改变这个值,就相当于你要在子类重新写一个,所以需要加override

trait PizzaTrait {
    /*抽象字段*/
    var numToppings:Int
    val ptype:String
    /*实际字段*/
    var size = 14
    val maxNumToppings = 10
}

class Pizza extends PizzaTrait{
    /*抽象字段不需要加override,而且变量修饰符应该和trait一样*/
    var numToppings: Int = 4
    val ptype: String = "thin"
    /*实际字段不需要加override,而且不需要加变量修饰符*/
    size = 16
    override val maxNumToppings = 20
}

 

三 像Java抽象类一样使用特质

抽象类:可以有抽象字段和抽象方法,也可以有非抽象字段和非抽象方法

注意:

如果一个继承了特质,但是并没有实现其抽象字段或者抽象方法,那么该类必须加abstract字段,意思就是说这个类必须为抽象类

 

trait Pet {
    var weight:Float
    def speakTo(who:String,sound:String){println("Towards "+who+", "+sound)}
    def actingCute
}

case class Cat(name:String) extends Pet{
    var color:String = ""
    var weight: Float = 0.0f
    def this(cname:String,color:String,weight:Float){
        this(cname)
        this.color = color
        this.weight = weight
    }
    override def actingCute: Unit = {
        println(s"$name is acting cute");
    }
    def desc(): Unit = {
        println(s"I'm $name, my color is $color")
    }
}

case class Dog(name:String) extends Pet{
    var ptype:String = ""
    var weight: Float = 0.0f
    def this(dname:String,ptype:String,weight:Float){
        this(dname)
        this.ptype = ptype
        this.weight = weight
    }
    override def actingCute: Unit = {
        println(s"$name is acting cute");
    }
    def desc(): Unit = {
        println(s"I'm $name, my belongs to $ptype")
    }
}

 

四 简单混入特质

说的明白些:其实就是继承抽象类并且混入withtrait

类似于Java中一个类继承了抽象类,实现了某一个接口

 

五 通过继承来限制特质的使用范围

特质可以限定哪些类来使用是可以的,比如说限定某些继承了某个类或者某个特质的类来使用这个trait

语法格式:

trait [traitname] extends [superthings]

一般情况下,某一个类可以随便继承其他父类,和混入其他的trait,但是有的时候,你只希望混入继承了该父类的trait才可以混入,否则混入不进来,这也就是限制了不能随意的混入

class StarfleetComponent
class RomulanStuff
trait StarfleetWrapCore1  extends StarfleetComponent


class Starship extends StarfleetComponent with StarfleetWrapCore1
//编译报错,因为StarfleetWrapCore 没有继承RomulanStuff
class Warbird1 extends RomulanStuff with StarfleetWrapCore1
/*如果我们这样修改就没有问题了*/
trait StarfleetWrapCore2  extends RomulanStuff
class Warbird2 extends RomulanStuff with StarfleetWrapCore2

 

六 限定特质只可用于指定类型的子类

通过语法this:指定类型 => 然后指定所允许混入的类或者其子类才可以混入该trait

 

class BaseType
class ParentType
trait MyTrait {
    /**
     * 指定该trait只能被BaseType的子类可以混入
     * 不是BaseType的子类是不可以混入这个trait
     */

    this:BaseType =>
}

class ConcreteType extends BaseType with MyTrait
/*所以这里会报错*/
class ImplementType extends  ParentType with MyTrait

 

七 保证特质只能被添加到只有一个特定方法的类型

允许特质混入到一个有给定签名的方法的类型(类,抽象类或者特质)

解决办法:

trait 特质名字{

      this:{def 函数名(参数:数据类型):返回值类型} =>

}

trait Limit {
    this:{ def validate(passwd:String):Boolean} =>
}

class Define extends Limit{
    //必须有这样的方法签名才可以混入Limit特质
    def validate(passwd:String):Boolean = {
        true
    }
}

 

八 为对象实例添加特质

有时候,我们可能只是想给某些对象添加特质,而不是针对类,即基于该类的对象,有的可以添加特质,有的不可以

语法格式:

new 类名字 with trait名字

class DavidBanner

trait Angry{
    println("You won't like me ...")
}

object Test extends App{
    val hunk = new DavidBanner with Angry
}

 

九 向特质一样继承Java接口

Scala中,我们可以像继承特质一样继承Java接口,通过with可以多继承,然后在类中实现java接口的方法

public interface Animal {
    public void speak();
}
public interface Wagging {
    public void wag();
}
public interface Running {
    public void run();
}

 

class Tiger extends Animal with Wagging with Running{
    override def speak(): Unit = {
        println("吼吼")
    }

    override def wag(): Unit = {
        println("摇尾巴")
    }

    override def run(): Unit = {
        println("奔跑中.....")
    }
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Scala中的特质Trait)是一种抽象机制,可以定义一组方法和字段,可以被混入(Mix-in)到类中,用于扩展类的功能。特质可以被多个类混入,从而实现了多重继承的效果。特质的定义方式类似于类,使用trait关键字。 Java中的接口(Interface)是一种抽象机制,可以定义一组方法,但不能定义字段。接口可以被类实现,用于实现多态性和封装性。接口的定义方式使用interface关键字。 Scala特质与Java的接口有以下联系和区别: 1. 联系:Scala特质和Java的接口都是一种抽象机制,用于定义一组方法,实现代码复用和多态性。 2. 区别: - 定义方式:Scala特质使用trait关键字定义,可以定义方法和字段,可以被类混入;Java的接口使用interface关键字定义,只能定义方法,不能定义字段。 - 实现方式:Scala特质可以被类混入,实现多重继承的效果;Java的接口只能被类实现,实现单一继承的效果。 - 默认实现:Scala特质可以定义具体的方法实现,被混入的类可以直接使用;Java的接口只能定义抽象方法,需要被实现类重写。 - 混入顺序:Scala特质可以定义继承顺序,被混入的类会按照特质的顺序依次调用方法;Java的接口没有定义继承顺序,实现类需要自行实现方法。 - 动态混入:Scala特质可以在运行时动态混入到类中;Java的接口只能在编译时实现。 综上所述,Scala特质比Java的接口更加灵活和强大,可以实现更多的功能和代码复用。但是,在实际应用中,需要根据具体的情况选择使用哪种机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫言静好、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值