在 Scala 中使用通用 case 类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18858164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:41:39  来源:igfitidea点击:

Using generic case classes in Scala

scalagenericscase-class

提问by Alexey Alexandrov

I wonder whether using generics for Scala case classes can save some boilerplate code.

我想知道对 Scala 案例类使用泛型是否可以节省一些样板代码。

Let's save I have the following class hieararchy to emulate a "variant" type that boxes a set of types and allows unboxing them using pattern matching:

让我们保存我有以下类层次结构来模拟“变体”类型,该类型将一组类型装箱并允许使用模式匹配将它们拆箱:

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"
}

There may be places in the code where it would be more convenient to deal with the leaf case classes if they were generics. Something like:

代码中可能有一些地方,如果叶子案例类是泛型,处理它们会更方便。就像是:

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"
}

But this doesn't compile. As far as I understand this syntax is not really recognized as valid Scala syntax.

但这不能编译。据我了解,这种语法并没有真正被认为是有效的 Scala 语法。

Is it possible to make what I want working or it's a bad idea and I just don't get something?

是否有可能使我想要的工作成为可能,或者这是一个坏主意而我只是没有得到一些东西?

EDIT:Vinicius answered my question, but looking at the answer I have another question. Is it possible to hint the compiler somehow that only certain list of types can be used to parameters TypedBox? I want that to make sure the compiler can still do exhaustiveness check of TypedBox usage/matching.

编辑:Vinicius 回答了我的问题,但查看答案我还有另一个问题。是否有可能以某种方式提示编译器只能将某些类型列表用于参数 TypedBox?我希望确保编译器仍然可以对 TypedBox 使用/匹配进行详尽检查。

回答by Vinicius Miana

Try

尝试

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"
}

回答by Morgen

For the second part of the question, there are two ways to limit the allowed types.

对于问题的第二部分,有两种方法可以限制允许的类型。

The first would be to put a bound on the type, which would limit the allowable types, but would not allow the compiler to do meaningful completeness checks as the types could be defined pretty much anywhere or any time.

第一个是在类型上设置一个界限,这将限制允许的类型,但不允许编译器进行有意义的完整性检查,因为几乎可以在任何地方或任何时间定义类型。

The second would be to wrap the type in a sealed trait, but then you are essentially creating a case class for each type, so you might as well remove the extra layer of wrapping and simply create DoubleBox, StringBox, etc.

第二是包装在密封的特质类型,但你基本上是创建每种类型的情况下类,所以你还不如去掉包装的额外层和简单的创建DoubleBoxStringBox等等。