scala 接受泛型类

标签 scala generics

我有两个案例类

abstract  class MainClass
case class Acc(x:String, y:String)  extends MainClass
case class Bcc(x:String, y:String)  extends MainClass

我需要编写一个通用函数,它将采用其中一个并返回相同案例类的列表,类似于:

def f1[T <: MainClass ]():List[T]={
val o1 = new Acc("sss","ddd").asInstanceOf[T]
List(o1)
}

唯一的问题是我对类型类“Acc”进行硬编码。我的问题是如何使 f1 方法实例化泛型类 T 而不是 Acc 或 Bcc

提前致谢。

最佳答案

虽然 ClassTag 解决方案可能适合您,但依赖运行时反射是一种代码味道,它实际上会给您带来真正的麻烦。假设您最终得到一个像这样的新子类(由您或其他人使用您的代码定义):

case class Ccc(x: String, y: String, i: Int)  extends MainClass

现在,当有人编写 f1[Ccc] 时(并且方法签名中没有表明他们不应该这样做),他们的程序将在运行时崩溃并出现 NoSuchMethodException

有一种更安全的方法来做这种事情,虽然它需要你编写一些样板文件,但它对于使用你的代码的人(包括你自己)来说是透明的。首先定义 type class描述了如何创建 MainClass 的某些特定子类的实例:

trait MainClassFromStrings[T <: MainClass] {
  def apply(x: String, y: String): T
}

然后你编写一些类型类实例:

implicit def AccFromStrings: MainClassFromStrings[Acc] =
  new MainClassFromStrings[Acc] {
    def apply(x: String, y: String) = Acc(x, y)
  }

implicit def BccFromStrings: MainClassFromStrings[Bcc] =
  new MainClassFromStrings[Bcc] {
    def apply(x: String, y: String) = Bcc(x, y)
  }

现在您可以非常干净地编写 f1 了:

def f1[T <: MainClass](implicit fs: MainClassFromStrings[T]) =
  List(fs("sss", "ddd"))

然后:

scala> f1[Acc]
res0: List[Acc] = List(Acc(sss,ddd))

scala> f1[Bcc]
res1: List[Bcc] = List(Bcc(sss,ddd))

但是如果你尝试f1[Ccc],你会得到一个很好的编译时错误。

类型类在 Scala 中使用相当广泛(包括在标准库中)——在 Stack Overflow 中搜索 "type classes" in Scala将出现大量示例和讨论。

关于scala 接受泛型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24962927/

相关文章:

scala - 如何将sbt test/ScalaTest配置为仅显示失败?

scala - 如何将 Option 与 Spark UDF 结合使用

swift - 这个层次结构应该如何运作?

java - <T> T 和 T 在方法的返回类型中有什么区别?

java - 检查 Object 是否是 List<Object> 的实例

scala - Spark - Csv 数据用 scala 分割

scala - 使用 Spark-testing-base 进行 Spark 单元测试

list - 惰性求值步骤: filtering a list

java - 如何创建一个工厂,根据Java中的接口(interface)类型创建类?

java - 返回扩展 Enum 并实现和 Interface-Java 的泛型类