18

ケースクラスからの継承が許可されていないことは知っていますが、本当に必要な場合はどうしますか? 階層内に 2 つのクラスがあり、どちらにも多くのフィールドが含まれており、両方のインスタンスを作成できる必要があります。ここに私のオプションがあります:

  • スーパークラスをケースクラスではなく通常のクラスにすると、toString、equals、hashCode メソッドなどのすべてのケースクラスの利点が失われます。
  • ケースクラスのままにしておくと、ケースクラスから継承しないというルールを破ることになります。
  • 子クラスでコンポジションを使用すると、多くのメソッドを記述して他のクラスにリダイレクトする必要があります。これは、多くの作業を意味し、非 Scalaish に感じられることを意味します。

私は何をすべきか?よくある問題ではないでしょうか。

4

3 に答える 3

14

はい、これは非常に頻繁に発生する問題です。私が提案するのは、すべての親プロパティを持つ特性を作成し、それを実装するだけのケース クラスを作成してから、より多くのプロパティでそれを継承する別のクラスを作成することです。

sealed trait Parent {
  /* implement all common properties */
}

case class A extends Parent

case class B extends Parent {
  /*add all stuff you want*/
}

これをツリー、トレイトをノード、ケース クラスをリーフと考えるとわかりやすいでしょう。

親のニーズに応じて、特性または抽象クラスを使用できます。ただし、クラスのインスタンスを作成できるため、クラスの使用は避けてください。これはエレガントではありません。

編集:コメントで示唆されているように、すべてのケース クラスがパターン マッチングでカバーされていない場合、コンパイル時に例外を発生させるために特性を封印できます。たとえば、「Programming in Scala」の15.5章で説明されています

于 2012-05-18T07:30:28.033 に答える
6

継承を委任に置き換えるのはどうですか?

階層内の 2 つのクラスに多くの共有フィールドがある場合、委譲によってボイラープレート コードの量を削減できますか? そのようです:

case class Something(aa: A, bb: B, cc: C, payload: Payload)

sealed abstract class Payload

case class PayloadX(xx: X) extends Payload
case class PayloadY(yy: Y) extends Payload

そして、次Somethingのようにインスタンスを作成します。

val sth1 = Something('aa', 'bb', 'cc', PayloadX('xx'))
val sth2 = Something('aa', 'bb', 'cc', PayloadY('yy'))

そして、パターンマッチングを行うことができます:

sth1 match {
  case Something(_, _, _, PayloadX(_)) => ...
  case Something(_, _, _, PayloadY(_)) => ...
}

利点: (?)

  • PayloadXPayloadYを宣言するとき、 Somethingのすべてのフィールドを繰り返す必要はありません。

  • のインスタンスを作成すると、 との両方を作成するときに、 を作成するSomething(... Payload(..))コードを再利用できます。SomethingSomething(... PayloadX(..))...PayloadY

欠点:(?)

  • おそらくPayloadXYあなたの場合は実際には の真のサブクラスSomethingです。

  • something.payload.whatever単純にではなく、書く必要がsomething.whateverあります (特定のケースに応じて、これは良いことも悪いこともあると思いますか?)

于 2012-08-16T05:44:55.440 に答える
4

私もこの問題を調査しましたが、私の知る限り、得られる最高のものは次のとおりです。

各ケース クラスが、各ケース クラスが実装しなければならない抽象プロパティを定義する共通のトレイトから拡張されるようにする

ボイラープレートを(まったく)削除しませんが、ケースクラスの機能セットを失うことなく、ケースクラスが従わなければならない契約を定義します...

于 2012-05-18T07:30:03.720 に答える