特质不能有构造器参数,每个特质都有一个无参数的构造器。缺少构造器参数是特质与类之间唯一的技术差别。除此之外,特质可以具备类的所有特性,比如具体的和抽象的字段,以及超类。现在有如下情景:我们想通过特质来实现日志数据的输出,输出到某一个文件中
1、初始化特质字段
import java.io.PrintStream
trait Logger7{
def log(msg:String)
}
trait FileLogger7 extends Logger7{
val fileName:String
val out = new PrintStream(fileName)
override def log(msg: String): Unit = {
out.print(msg)
out.flush()
}
}
class SavingsAccount7{
}
object Main7 extends App {
val acct = new SavingsAccount7 with FileLogger7 {
override val fileName = "2019-05-03.log"//空指针异常
}
}
尖叫提示:报错,修复有两种方式
2、解决异常 方式一(提前定义)
import java.io.PrintStream
trait Logger7 {
def log(msg: String)
}
trait FileLogger7 extends Logger7 {
val fileName: String
val out = new PrintStream(fileName)
override def log(msg: String): Unit = {
out.print(msg)
out.flush()
}
}
class SavingsAccount7 {
}
object Main7 extends App {
//提前定义
val acct = new {
override val fileName = "2019-05-13.log"
} with SavingsAccount7 with FileLogger7
acct.log("heiheihei")
}
3、解决异常 方式二(提前定义)
package unit12
import java.io.PrintStream
trait Logger7 {
def log(msg: String)
}
trait FileLogger7 extends Logger7 {
val fileName: String
val out = new PrintStream(fileName)
override def log(msg: String): Unit = {
out.print(msg)
out.flush()
}
}
//提前定义在这里
class SavingsAccount7 extends {
override val fileName = "2019-05-13.log"
} with FileLogger7
object Main7 extends App {
val acct = new SavingsAccount7
acct.log("嘿嘿嘿")
}
4、解决异常 方式三(使用lazy)
package unit12
import java.io.PrintStream
trait Logger7 {
def log(msg: String)
}
trait FileLogger7 extends Logger7 {
val fileName: String
lazy val out = new PrintStream(fileName)
override def log(msg: String): Unit = {
out.print(msg)
out.flush()
}
}
class SavingsAccount7 {
}
object Main7 extends App {
val acct = new SavingsAccount7 with FileLogger7 {
override val fileName = "2017-11-24.log"
}
acct.log("哈哈哈")
}
尖叫提示:解决问题的手段和方式,不用记太多,需要记住的是构造顺序,不管是提前定义还是懒加载,主要解决的都是构造顺序的问题