7

抽象クラスとトレイトのどちらを選択するかについていくつかの議論があったことに気付きましたが、次の点に焦点を当てたものはなかったようです。私が抽象クラスを使用するようになった理由の 1 つは、それらはコンストラクター パラメーターを持つことができますが、トレイトはそれができないことです。しかし、なぜ次の

trait X {
  def haha: Int
}
class Y(val haha: Int) extends X

そして、すべてを適切に機能させるために早期定義は必要ありません(私は心配していました)。抽象クラスのバージョンは

abstract class X(haha: Int)
class Y(val haha: Int) extends X(haha)

抽象クラスのバージョンは好きではありません。何度か拡張すると、これらのコンストラクターのパラメーターがいたるところに現れるからです (誰かがこれを回避する方法を教えてくれるのではないでしょうか?)。

抽象クラスは Java をより適切に補間し、「is-a」の概念により適合することを認識しています。これらにもかかわらず、どこかで抽象クラスを使用する必要がある理由はありますか? ありがとう!

4

1 に答える 1

9

クラス パラメーターは、メンバー (フィールドまたは定義) である必要はありません。

abstract class X(haha: Int) {
  val hoho = 2 * haha  // compile-time constant
}

同様に、特性の初期化順序は線形化 (混合順序) に依存します。これが、特性メンバーが val ではなく def であるべき理由です。(そして、いつでも val で def をオーバーライドできます。) 抽象クラスを使用すると、自分のスーパーが誰であるかがわかり、サブクラスの拡張ポイントを定義できます。

ただし、抽象クラスの val が間違った場所にあることに注意してください。

abstract class X(val haha: Int)
class Y(haha: Int) extends X(haha)

つまり、param が val であるかどうかを X が判断することが期待されます (そうである必要はありません)。X または Y のいずれかで param を使用すると、フィールドに変わる可能性があります。

クラスの値パラメーターに関するあなたの観察は、型パラメーターにも当てはまります。階層の上に Foo[A] を渡すのはなんと面倒なことでしょう。そのため、Scala では、代わりにメンバー型 A を使用できます。これは、リーフで定義されるまで抽象のままにすることができます。しかし、これは実際には、トレイトを定義するかクラスを定義するかには関係ありません。

しかし、特性パラメーターは Scala に来ています。(この理由で優先度の低い初期の定義については、Scala バグを参照してください。)

于 2012-12-11T22:33:33.317 に答える