scala接受泛型类

时间:2014-07-25 19:11:28

标签: 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)
}

唯一的问题是我正在对类型类进行硬编码&#34; Acc&#34; 。我的问题是如何让f1方法实例化泛型类T而不是Acc或Bcc

提前谢谢。

2 个答案:

答案 0 :(得分:11)

虽然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中被广泛使用(包括在标准库中) - 搜索"type classes" in Scala的Stack Overflow将会提供大量示例和讨论。

答案 1 :(得分:1)

  

您可以使用ClassTag保存有关Class的元信息   运行时。

import scala.reflect._


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

object  Boot extends App {



  def f1[T <: MainClass : ClassTag ]():List[T]={
    val o1 = classTag[T].runtimeClass.getConstructor(classOf[String], classOf[String]).newInstance("sss","ddd").asInstanceOf[T]
    List(o1)
  }

 val list =  f1[Acc]

}