Scala入门到精通——第十一节 Trait进阶

本文详细探讨了Scala中的Trait,包括构造顺序、与类的区别、提前定义与懒加载、Trait扩展类以及self type。讲解了Trait构造过程中先调用超类和父Trait构造器的规则,对比了Trait与类的异同,并举例说明了如何解决 Trait 中构造器顺序导致的问题,如使用lazy关键字。此外,还介绍了Trait扩展类的用法和self type的概念及其在内部类和抽象类中的应用。
摘要由CSDN通过智能技术生成

本节主要内容

  1. trait构造顺序
  2. trait与类的比较
  3. 提前定义与懒加载
  4. trait扩展类
  5. self type

1 trait构造顺序

在前一讲当中我们提到,对于不存在具体实现及字段的trait,它最终生成的字节码文件反编译后是等同于java中的接口,而对于存在具体实现及字段的trait,其字节码文件反编译后得到的java中的抽象类,它有着scala语言自己的实现方式。因此,对于trait它也有自己的构造器,trait的构造器由字段的初始化和其它trait体中的语句构成,下面是其代码演示:

package cn.scala.xtwy

import java.io.PrintWriter

trait Logger{
  println("Logger")
  def log(msg:String):Unit
}

trait FileLogger extends Logger{
  println("FilgeLogger")
  val fileOutput=new PrintWriter("file.log")
  fileOutput.println("#")

  def log(msg:String):Unit={
    fileOutput.print(msg)
    fileOutput.flush()
    }
}
object TraitDemo{
  def main(args: Array[String]): Unit = {
    //匿名类
    new FileLogger{  
    }.log("trat demo")
  }
}
//打印输出内容为:
Logger
FilgeLogger
//创建文件file.log,内容为
#
trat demo

通过上述不难发现,在创建匿名类对象时,先调用的是Logger类的构造器,然后调用的是FileLogger的构造器。实际上构造器是按以下顺序执行的:
1. 如果有超类,则先调用超类的构造器
2. 如果有父trait,它会按照继承层次先调用父trait的构造器
2. 如果有多个父trait,则按顺序从左到右执行
3. 所有父类构造器和父trait被构造完之后,才会构造本类

class Person
class Student extends Person with FileLogger with Cloneable
上述构造器的执行顺序为:
1 首先调用父类Person的构造器
2 调用父trait Logger的构造器
3 再调用trait FileLogger构造器,再然后调用Cloneable的构造器
4 最后才调用Student的构造器

2 trait与类的比较

通过前一小节,可以看到,trait有自己的构造器,它是无参构造器,不能定义trait带参数的构造器,即:

//不能定义trait带参数的构造器
trait FileLogger(msg:String) 

除此之外 ,trait与普通的scala类并没有其它区别,在前一讲中我们提到,trait中可以有具体的、抽象的字段,也可以有具体的、抽象的方法,即使trait中没有抽象的方法也是合理的,如:

//FileLogger里面没有抽象的方法
trait FileLogger extends Logger{
   
  println("FilgeLogger")
  val fileOutput=new PrintWriter("file.log")
  fileOutput.println("#")

  def log
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值