web-dev-qa-db-ja.com

Scala

Scalaケースクラスにジェネリックスを使用すると、定型コードを節約できるかどうか疑問に思います。

型のセットをボックス化し、パターンマッチングを使用してボックス化を解除できる「バリアント」型をエミュレートするために、次のクラス階層があることを保存しましょう。

sealed abstract class Box;

case class DoubleBox(v: Double) extends Box;
case class StringBox(v: String) extends Box;
case class BooleanBox(v: Boolean) extends Box;

def typeName(b: Box) = b match {
  case DoubleBox(v) => "Double"
  case StringBox(v) => "String"
  case BooleanBox(v) => "Boolean"
  case _ => "Unknown"
}

リーフケースクラスがジェネリックである場合、それらを処理する方が便利な場所がコード内にある可能性があります。何かのようなもの:

sealed abstract class Box;

case class TypedBox[T](v: T) extends Box;

def typeName2(b: Box) = b match {
  case TypedBox[Double](v) => "Double"
  case TypedBox[String](v) => "String"
  case TypedBox[Boolean](v) => "Boolean"
  case _ => "Unknown"
}

しかし、これはコンパイルされません。私が理解している限り、この構文は実際には有効なScala構文として認識されていません。

私がやりたいことを作ることは可能ですか、それとも悪い考えで、私は何かを得られませんか?

編集:ビニシウスは私の質問に答えましたが、答えを見ると別の質問があります。 TypedBoxのパラメーターに使用できるのは特定のタイプのリストのみであることをコンパイラーに示唆することは可能ですか?コンパイラがTypedBoxの使用法/マッチングの徹底的なチェックを実行できることを確認したいと思います。

16

試してみてください

sealed abstract class Box;

case class TypedBox[T](v: T) extends Box;

def typeName2(b: Box) = b match {
  case TypedBox(v: Double) => "Double"
  case TypedBox(v: String) => "String"
  case TypedBox(v: Boolean) => "Boolean"
  case _ => "Unknown"
}
25
Vinicius Miana

質問の2番目の部分では、許可されるタイプを制限する2つの方法があります。

1つ目は、型に境界を設定することです。これにより、許容される型が制限されますが、型はほぼどこでも、いつでも定義できるため、コンパイラーは意味のある完全性チェックを実行できません。

2つ目は、型を封印された特性でラップすることですが、基本的には型ごとにケースクラスを作成するため、余分なラッピングレイヤーを削除して、単にDoubleBoxStringBoxなど。

1
Morgen