博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
trait
阅读量:7045 次
发布时间:2019-06-28

本文共 3515 字,大约阅读时间需要 11 分钟。

hot3.png

trait

老实说,感觉traitJava中的interface已经很像了,因此下面我们主要说不像的.

  1. Javaimplements来实现接口, scalaextendswith来实现接口

    先看一个经典的有关日志的例子

    object TraitAddExtra {  def main(args: Array[String]): Unit = {    val savingsAccount = new SavingsAccount1    savingsAccount.deposit(1000)    savingsAccount.withDraw(300)    savingsAccount.withDraw(800)  }}trait MyLogger1 {  def log(msg: String)  def info(msg: String) = log("INFO\t" + msg)  def warn(msg: String) = log("WARN\t" + msg)  def err(msg: String) = log("ERR\t" + msg)}class SavingsAccount1 extends Acount(0, 0) with MyLogger1 {  def withDraw(amount: Double): Unit = {    if (amount > balance) err("Insufficient funds")    else {      balance -= amount      info("withDraw money" + amount)      warn("remained money" + balance)    }  }  override def log(msg: String): Unit = println(msg)}
    class Acount (val id: Int, initialBalance: Double) {  var balance = initialBalance  def deposit(amount: Double): Double = {    balance += amount    balance  }  override def toString: String = id + "->" + balance}object Acount {  private var lastNumber = 0  println("i am in constructor of object")  def newUniqueNumber(): Int = {    lastNumber += 1    lastNumber  }  def apply(initialBalance: Double): Acount = new Acount(newUniqueNumber(), initialBalance)  def main(args: Array[String]): Unit = {    val accounts = ArrayBuffer[Acount](Acount(100.0), Acount(1000.0), Acount(10000.0))    accounts.foreach(println)  }}
    • 通过以上代码我们发现,scala在这点上和java上没有多大区别,接口里都可以定义抽象方法和具体方法.
  2. trait引入的处理--scala这里采用从最后一个开始倒着处理.(这个说明一下,这种功能java无法实现,无论你用interface还是abstract,均无法调用super.log()这个方法,故无法完成,其实Java里这里采用策略设计模式会去实现,但是也非常不好用,还得靠组合函数去实现.这里就体现出了scala的优势,确实非常舒服!)

    object TraitWhenOverlying extends App {  //先调用ShortLogger 调用super.log为TimestampLogger调用super.log为PrintLogger  val act1 = new SavingsAccount with PrintLogger with TimestampLogger with ShortLogger  //先调用TimestampLogger 调用ShortLogger调用super..log为PrintLogger  val act2 = new SavingsAccount with PrintLogger with ShortLogger with TimestampLogger  //如果你想指定调用特定的trait,用super[Trait].log()  //  val act3 = new SavingsAccount with LongLogger with PrintLogger  act1.deposit(1000)  act1.withDraw(400)  act1.withDraw(700)  act2.deposit(1000)  act2.withDraw(400)  act2.withDraw(700)  /*act3.deposit(1000)  act3.withDraw(400)  act3.withDraw(700)*/}trait TimestampLogger extends PrintLogger {  override def log(msg: String): Unit = {    println("我被调用了,我在TimestampLogger里")    super.log(new Date() + "\t" + msg)  }}trait ShortLogger extends PrintLogger {  val maxLength = 15  override def log(msg: String): Unit = {    println("我被调用了,我在ShortLogger里")    super.log(if (msg.length <= maxLength) msg else msg.substring(0, maxLength - 3) + "...")  }}

    结果

    我被调用了,我在ShortLogger里我被调用了,我在TimestampLogger里Tue Jan 09 16:42:16 CST 2018	Insufficient...我被调用了,我在TimestampLogger里我被调用了,我在ShortLogger里Tue Jan 09 1...

  3. trait的初始化顺序:注意和上面的super.log比较,会发现方向正好相反,初始化是按照顺序正常构造,super是从右向左来调用,前者的顺序化是线性化的反向,后者的顺序是线性化的方向.

    • 首先调用超类的构造器
    • trait构造器在超类构造器之后,在类构造器之后.
    • trait构造器由左到右被构造
    • 每个trait中,父构造器先被构造
    • 如果多个trait共有一个父trait,而那个父trait已经被构造,则不会被再次构造
    • 所有trait构造完毕,类被构造

    class SavingAcount extends Acount with FileLogger with ShortLogger为例

    • Acount(超类)
    • Logger(第一个trait的父trait)
    • ShortLogger(第一个trait)
    • FileLogger(第二个trait)
    • SavingAcount(类)
  4. trait和类之间的唯一技术差别就是trait不能右构造器,只有一个默认的无参构造器.你应该记得object也是这样,不能有构造器,其他的特性都有.

  5. trait原理

    • trait会被翻译成为JVM的类和接口

    • 抽象方法翻译为接口的抽象方法

    • 具体方法翻译为Java的默认方法

    • 如果有字段:

      • 翻译成接口就有getter,setter方法,其实出国初始化了的化,还会翻译成一个init方法

      • 如果有类继承这个trait,则会此类会获得这个字段,相当于java里的private ...

转载于:https://my.oschina.net/xd03122049/blog/1605327

你可能感兴趣的文章
1.1.2 C++发展历程
查看>>
我的友情链接
查看>>
awk笔记
查看>>
apache使用.htaccess进行基于文件扩展名的访问控制
查看>>
Hystrix降级技术解析-Fallback
查看>>
Windows XP 禁用防火墙、系统升级、系统还原指南
查看>>
让你的电脑变成wifi
查看>>
xshell 隧道透传
查看>>
zabbix-server添加zabbix-proxy
查看>>
iostat命令找不到
查看>>
外观模式
查看>>
我的友情链接
查看>>
Angular2 AoT编译以及Rollup摇树优化
查看>>
ReactJS 学习资料汇总
查看>>
IIS权限应该怎么给?
查看>>
SpringMVC 拦截器和过滤器的区别&&Struts2拦截器和过滤器的区别
查看>>
Linux安装mysql
查看>>
linux 使用全攻略
查看>>
Access:collating sort order SortOrder[2052(0)]
查看>>
Spark算子:RDD基本转换操作(1)–map、flagMap、distinct
查看>>