如何匹配scala泛型类型与特征

时间:2015-04-10 16:41:35

标签: scala generics scala-2.10

这是传入DatabaseType的原始方法。

trait DatabaseComponent

class Database {
  this: DatabaseComponent =>

}

object Database {
  def apply(dbType : DatabaseType): Unit ={
    val database = dbType match {
      case DatabaseType.H2 => new Database with H2Component {}
      case DatabaseType.MySQL => new Database with MySQLComponent {}
      case DatabaseType.PostgresSQL => new Database with PostgresSQLComponent {}
    }
  }
}

但是,我希望传递泛型类型并使用{C}

中的typeOf(T)
private void Apply<T>(){
   switch(typeOf(T)){
     Something
   }
}

我正在看这篇文章How to match scala generic type?

但我仍然不确定这是做什么的。

1)与val string = implicitly[ClassTag[String]]

隐含有关

2)为什么T必须是ClassTag的子类implicitly[ClassTag[T]] match {

3)我应该在这里使用ClassTag还是TypeTag?

2 个答案:

答案 0 :(得分:1)

1和2有相同的答案,您可能想要阅读类型类。这里的类型是ClassTag [T]。从本质上讲,类型类是一个可以“附加”的接口。通过称为类型类实例的实现到任何类型。在Scala中,类型类的实例在隐式作用域中查找,因此虽然您可以为类型实现多个不同的实例,但是可能永远不会有多个实现(或者它是不明确的)。如果你写了像

这样的东西
def method[T : TypeClass](p1, p2, ...) 

在调用方法时,强制在范围内为类型T设置TypeClass实例。请注意,这相当于

def method[T](p1, p2, ...)(implicit val ev: TypeClass[T]) ...

所以你实际上有一个隐藏的参数,你可以明确地给出(!)

隐式[X]实际上是一种获取生活在当前范围内的X型隐式值的方法。你可以自己实现它:

def yourImplicitly[T](implicit val ev: T) : T = ev

类型类有很多应用程序,因为这是一种富有成效的抽象。您可能想要了解&#34;扩展问题&#34;,因为类型类是FP语言扩展问题的解决方案。

实际上,您可能会将DatabaseComponent本身设为类型类。

  1. 我不太清楚这里的答案,你可能想查看http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html。如果我正确理解你的问题,那么类标签就足够了(并且更容易使用)。

答案 1 :(得分:0)

部分补充@uberwach的答案

与C#不同,JVM具有类型擦除功能,可在运行时删除所有类型的日期。所以在Scala中不可能typeOf。您无法在运行时创建类型为T的新实例。

Type erasure: Java vs C#