Chapter10

package scala

import java.io.{PrintStream, PrintWriter}
import java.util.Date

import scala.util.logging.{ConsoleLogger, Logged}


/**
* Created by EX-CHENZECHAO001 on 2018-04-03.
*/
class Chapter10 {

}

// 10.6 在特质中重写抽象方法
trait Logger1006 {
def log(msg: String) // 抽象方法
}

trait TimestampLogger1006 extends Logger1006 {
// 重写抽象方法
abstract override def log(msg: String): Unit = { // 必须给方法打上abstract和override关键字
super.log(new java.util.Date() + "" + msg) // 无定义super.log
}
}

// 10.7 当做富接口使用的特质
trait Logger1007 {
def log(msg: String)
def info(msg: String){log("INFO: " + msg)}
def warn(msg: String) {log("WARN: " + msg)}
def servere(msg: String) {log("SERVERE: " + msg)}
}

// 10.8特质中的具体字段
trait shortLogger extends Logged{
val maxLength = 15
}
class Account1008 {
var balance = 0.0
}
class SavingsAccount1008 extends Account1008 with ConsoleLogger with shortLogger{
var interest = 0.0
def withdraw(amount: Double): Unit = {
if(amount > balance) {
log("Insufficient funds")
}
}
}

// 10.9 特质中的抽象字段
trait ShortLogger1009 extends Logged {
val maxLength: Int // 抽象字段
override def log(msg: String) {
super.log{
if(msg.length <= maxLength){
msg
}else {
msg.substring(0,maxLength - 3) + "..."
}
}
}
}
// 当在具体的类中使用该特质时,必须提供maxLength字段
class SavingsAccount1009 extends Account1008 with ConsoleLogger with ShortLogger1009 {
val maxLength = 10 // 可不需写override
}
class SavingsAccount {
}
object ShortLogger1009 {
val acct = new SavingsAccount with ConsoleLogger with ShortLogger1009 {
override val maxLength: Int = 10
}
}

// 10.10 特质构造顺序
// 和类一样,特质也可以有构造器,由字段的初始化和其它特质体中的语句构成
trait FileLogger1010 extends Logger1006 {
val out = new PrintWriter("app.log")
out.println("# " + new Date().toString)
def log(msg: String) {out.println(msg);out.flush()}
}
// 这些语句在任何混入该特质的对象在构造时都会被执行
// 构造器以如下顺序执行:
// 首先调用 超类的构造器
// 特质构造器在超类构造器之后、类构造器之前执行
// 特质由械到右被构造
// 每个特质当中,父特质先被构造
// 如果多个特质共有一个父特质,而那个父特质已经被构造,则不会再次构造
// 所有特质构造完毕,子类被构造

class SavingsAccount1010 extends Account1008 with FileLogger1010 with ShortLogger1009 {
override val maxLength: Int = 10
}
// 构造器将按照如下的顺序执行:
// 1.Account1008 超类
// 2.Logger 第一个特质的父特质
// 3.FileLogger1010 第一个特质
// 4.ShortLogger1009第二个特质,其父特质logger已被构造
// 5.SavingsAccount1010类
/////////// 重看

// 10.11 初始化特质中的字段
// 特质不能有构造参数。每个特质都有一个无参数的构造器
// 缺少构造器参数是特质与类之间唯一的技术差别。除此之外,特质可以具备类的所有特性,比如具体的和抽象的字段,以及超类。
// 特质可以使用抽象字段当参数,需使用提前定义
trait FileLogger1011 extends Logger1006 {
val filename: String // 抽象字段
val out = new PrintStream(filename)
def log(msg: String) {out.println(msg);out.flush()}
}

object FileLogger1011 {
val acct1011 = new { // new之后的提前定义块
val filename = "myapp.log"
} with SavingsAccount1008 with FileLogger1011
}
// 提前定义发生在常规的构造序列之前。
// 类的提前定义
class SavingsAccount1011 extends { // extends后是提前定义块
val filename = "savings.log"
} with Account1008 with FileLogger1011 {
// SavingsAccount1011的实现
}
// 另一个解决方法是在FileLogger构造器中使用懒值,不过由于懒值在每次使用前都会检查是否已经初始化,效率不高

// 10.12 扩展类的特质






































原文地址:https://www.cnblogs.com/chenzechao/p/8709829.html