我想知道在Scala案例类中使用泛型是否可以节省一些样板代码。
让我们保存我有以下类hieararchy来模拟一个“变体”类型,它包含一组类型,并允许使用模式匹配拆箱:
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语法。
是否有可能制作出我想要的作品,或者这是一个坏主意,我只是没有得到什么?
编辑: Vinicius回答了我的问题,但看到答案我还有另一个问题。是否有可能以某种方式提示编译器只有某些类型的列表可用于参数TypedBox?我希望这样做以确保编译器仍然可以对TypedBox的使用/匹配进行详尽的检查。
答案 0 :(得分:23)
尝试
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"
}
答案 1 :(得分:1)
对于问题的第二部分,有两种方法可以限制允许的类型。
第一种方法是对类型进行绑定,这将限制允许的类型,但不允许编译器进行有意义的完整性检查,因为几乎可以在任何地方或任何时间定义类型。
第二种方法是将类型包装在一个密封的特征中,但是你实际上是为每种类型创建一个case类,所以你不妨删除额外的包装层,只需创建DT1 <- data.table(x = letters[1:6], y1 = 10:15)
DT2 <- data.table(x = letters[1:6], y2 = 11:16)
DT3 <- data.table(x = letters[1:6], y3 = 12:17)
DT4 <- data.table(x = letters[1:6], y4 = 13:18)
DT5 <- data.table(x = letters[1:6], y5 = 14:19)
DT6 <- data.table(x = letters[2:7], y6 = 15:20, key="x")
,{ {1}}等等。