我對特性構造函數的順序有疑問。關於特質構造函數的命令的訂單
class Account(initialBalance: Double) extends ConsoleLogger {
private var balance = initialBalance
def withdraw(amount: Double) = {
if (amount > balance) log("Insufficient funds")
else {
balance -= amount;
balance
}
}
def getAccount = balance
}
trait Logged {
def log(msg: String): Unit = {}
}
trait ConsoleLogger extends Logged {
override def log(msg: String): Unit = {
println(msg)
}
}
trait TimestampLogger extends Logged {
override def log(msg: String) {
super.log(new Date() + " " + msg)
}
}
trait ShortLogger extends Logged {
val maxLength = 15
override def log(msg: String) {
super.log(if (msg.length <= maxLength) msg else msg.substring(0, maxLength - 3) + "...")
}
}
object test9 extends App {
val acct1 = new Account(100) with ConsoleLogger with TimestampLogger with ShortLogger
val acct2 = new Account(100) with ConsoleLogger with ShortLogger with TimestampLogger
acct1.withdraw(500)
acct2.withdraw(500)
}
結果是:
> Sun Sep 20 21:25:57 CST 2015 Insufficient...
> Sun Sep 20 2...
所以在acct1,弗里斯特是ShortLogger.log,第二個是TimestampLogger.log。 在acct2中,第一個是TimestampLogger.log,第二個是ShortLogger.log
但是正如我知道的,trait構造函數的順序是從左到右。 因此,acct1的特質構造函數順序是Logged,ConsoleLogger,TimestampLogger,ShortLogger。 爲什麼要首先執行ShortLogger.log?
這是線性化ru les:https://www.artima.com/pins1ed/traits.html。在我看來,他們是Scala中最瘋狂的部分,同時還有隱含的解析規則。一旦確定了層次結構的線性化,那麼「當這些類和特徵中的任何一個通過super調用一個方法時,被調用的實現將是線性化的第一個實現。」 –