Scala语言基础(七)trait

特质(trait)的定义

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

trait Animal01 {
  def eat():Unit
  def exercise():String
}
trait Animal02{
  def eat02():Unit
  def exercise02():String
  def color():Unit={
    println("this dog is black")
  }
}
//实现一个trait使用extends
class Dog01 extends Animal01{
  override def eat(): Unit = {println("A dog loves eating meat")}

  override def exercise(): String = {
    "A dog loves running!"
  }
}

//实现多个trait第一个使用extends,其余使用with A with B。。。
//如果有类,这类使用extends,trait使用with,一次继承只能继承一个类,和java一样
class Dog02 extends Animal01 with Animal02{
  override def eat(): Unit = {println("This dog loves eating leaves")}

  override def exercise(): String = {"loves running"}

  override def eat02(): Unit = {println("loves eating meat")}

  def exercise02(): String = {"loves crawling"}//trait未实现的方法可以不带关键字override

  override def color(): Unit = {println("it becomes white")}//trait实现的方法必须带关键字override
}

object TestDemo{
  def main(args: Array[String]): Unit = {
   val dog01 = new Dog01()
    dog01.eat()

    val dog02 = new Dog02//无参构造器可以不带括号
    dog02.eat//无参方法也可以不用带括号
  }
}

总结:
Java中:
1,接口是一种特殊的抽象类
2,里面所有方法都是抽象方法
scala中:
1,特质里面的方法既可以实现,也可以不实现,
2,抽象类使用extends单继承
3,实现特质,如果没有继承其他类,第一个特质使用extends,后面使用with,所以实现特质有两种情况:
a. 实现一个特质使用extends
b. 实现两个及以上,第一个使用extends,后面的使用with
Trait的几种不同使用方式:
1,当做Java接口使用的trait都是抽象字段和抽象方法
2,带实现方法的trait
3,带具体字段的trait
Traits的底层实现采用Java的抽象类。

初始化顺序

object ParentConstructor {
    def main(args: Array[String]): Unit = {
        //执行顺序时先初始化父类,在执行本身,由于实现了A接口,所以初始化A接口,再初始化本身
        val c: C = new C //执行顺序为:trait B->trait A->trait C
    }
}

trait A {
    println("trait A")
}

class B  {
    println("trait B")
}

class C extends B with A{
    println("trait C")
}
object ParentConstructor {
    def main(args: Array[String]): Unit = {
        //特质和父类没有关系,只和当前混入的类有关系,所以在调用时,父类先执行,
        // 然后当前混入的特质再执行,然后当前类再执行
        //如果父类混入了相同的特质,那么特质代码只会执行一次
        val c: C = new C //执行顺序为:trait A->trait B->trait C
    }
}

trait A {
    println("trait A")
}

class B extends A {
    println("trait B")
}

class C extends B with A{
    println("trait C")
}

混入

trait MixedTest {
  def travelling(msg:String):Unit={}
}
trait MixedTest02 extends MixedTest{
  override def travelling(msg: String): Unit = {
    println("MixedTest02: "+msg)
  }
}
trait MixedTest03 extends MixedTest{
  override def travelling(msg: String): Unit = {
    println("MixedTest03: "+msg)
  }
}
class Test(val name:String) extends MixedTest02{
  def hello():Unit={
    println("hello "+ name)
    travelling("hello is invoked")//实现MixedTest02的方法
  }
}
object TestDemo02{
  def main(args: Array[String]): Unit = {
    val test=new Test("xh")
    test.hello()//结果是   //hello xh    //MixedTest02: hello is invoked

    //混入方法
    val test02 = new Test("小黑") with MixedTest03
    test02.hello()//结果是     //hello 小黑   //MixedTest03: hello is invoked
    //可以看到其调用的travelling方法是MixedTest03的,也就是说,这种方法可以改变已经
    //定型的类的方法的具体实现
  }
}
object ParentConstructor {
    def main(args: Array[String]): Unit = {
        val sql: MySql = new MySql
        sql.insert()
    }
}

trait Operate {
    println("Operate......")

    def insert(): Unit = {
        println("插入数据")
    }
}

trait DB extends Operate {
    println("DB......")

    override def insert() {
        println("向数据库")
        super.insert()
    }
}

trait File extends Operate {
    println("File......")

    override def insert(): Unit = {
        println("向文件")
        super.insert()
    }
}

//多特质混入时,代码执行顺序为从左到右,如果有父类特质,会优先执行
// 多特质混入时,方法调用的顺序为从右到左
// 特质中super关键字不是指代父特质,指代上一级特质
//如果希望super指向父特质,需要增加特殊操作:super[特质]
//Java中的接口可以当作Scala中的特质使用
class MySql extends DB with File {

}

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 TraitChain(val name:String) extends Handler_C with Handler_B with Handler_A{
  def sayHello()={
    println("hello "+ name)
    handler(name)
  }
}
object HandlerTest{
  def main(args: Array[String]): Unit = {
    val traitChain = new TraitChain("xh")
    traitChain.sayHello()

    /**
     * 结果:
     * hello xh
     * Handler_A: xh
     * Handler_B: xh
     * Handler_C: xh
     * 也就是说形成这种链表(每个trait调用父类方法很重要,即:super.handler(data))后,
     * 对子类这些trait是平等的,他们的方法都会调用,只是从前后往前,
     */
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值