2

だから私はScala for the Impatient の本を読んでいて、それが使用する例の 1 つは、本質的に何らかのストリームにLoggera を出力する特性です。この例では、メッセージを出力Stringする特性ConsoleLogger( extends )と( extends も拡張) があり、長さが長すぎる場合は単純に文字列を切り捨てます。本の最大長を変更するには、次のような匿名サブクラスを使用することを提案します。LoggerstdoutShortLoggerLoggerShortLogger

val acct = new SavingsAccount with ConsoleLogger with ShortLogger {
  val maxLength = 20
}

whereは抽象フィールドをShortLogger持つ特性であり、次のように定義されますmaxLength: IntSavingsAccount

class SavingsAccount extends Account with Logged { ... }

これは私には理にかなっています(一種の)。私は構築順序が次のとおりであると仮定しています。

  1. Logger最初に構築されます (これは のスーパートレイトであるためConsoleLogger)、
  2. ConsoleLogger
  3. ShortLogger
  4. Account
  5. SavingsAccount.
  6. 次に、abstract を定義する無名サブクラスの構築がありますmaxLength = 20

ただし、本の後半では、新しいLoggerサブ特性を提供します。

trait FileLogger extends Logger {
  val filename: String
  val out = new PrintStream(filename)
  def log(msg: String) { out.println(msg); out.flush() }
}

val acct = new SavingsAccont with FileLogger {
  val filename = "myapp.log" // Does not work
}

工事順で動かないとのこと。彼らは修正を提案します:

val acct = new {
  val filename: "myapp.log"
} with SavingsAccount with FileLogger

ただし、この定義は上記の と似ているmaxLengthようですが、上の例と下の例の間に何が欠けているのでしょうか?

4

1 に答える 1

5

あなたの建設順序は完全に間違っています。:-)

最初に構築されるのはクラスで、次にトレイトを左から右に見ていきます。それはもう少し複雑です。複数回継承された特性を処理する線形化ルールがありますが、それだけです。

そう:

  1. アカウント
  2. 記録された
  3. 普通預金口座
  4. ConsoleLogger
  5. ショートロガー
  6. 匿名サブクラス

さて、あなたの質問に:

val acct = new SavingsAccont with FileLogger {
  val filename = "myapp.log" // Does not work
}

val acct = new {
  val filename: "myapp.log"
} with SavingsAccount with FileLogger

2 番目の例では、コード ブロックが最初に来ることに注意してください。これは初期初期化と呼ばれ、その初期化を何よりも先に適用します。

于 2012-07-04T22:46:35.877 に答える