Scala:在reflect.runtime.universe.Type上进行模式匹配?

时间:2015-02-03 14:50:28

标签: scala types pattern-matching

如何在reflect.runtime.universe.Type上进行模式匹配?

def test(t: reflect.runtime.universe.Type) {
  t match {
    case Int => \\ ...
    case Double => \\ ...
    case String => \\ ... 
    case _ =>  \\ ...
  }
}    

正如翻译所抱怨的那样,这个工作没有用。

error: pattern type is incompatible with expected type;
 found   : Int.type
 required: reflect.runtime.universe.Type
Note: if you intended to match against the class, try `case _: Int`
         case Int => // ...
              ^

尝试该建议也不起作用:

def test(t: reflect.runtime.universe.Type) {
  t match {
    case _: Int => \\ ...
    case _: Double => \\ ...
    case _: String => \\ ... 
    case _ =>  \\ ...
  }
}    

...

error: pattern type is incompatible with expected type;
 found   : Int
 required: reflect.runtime.universe.TypeApi
            case _: Int => // ...
                 ^

那么这个的正确语法是什么?

谢谢!

3 个答案:

答案 0 :(得分:5)

TypeTag API有一个比较运算符=:=和一个获取给定类的Type实例的方法,您可以将它们与守卫结合起来以获得所需的结果:

import scala.reflect.runtime.universe._

def test(t: Type) {
  t match {
    case t if t =:= typeOf[Int] => println("int")
    case t if t =:= typeOf[String] => println("string")
    case _ =>  
  }
} 

答案 1 :(得分:0)

正如lmm和n1r3指出的那样,你可能最好使用if if here。但是,您可以执行以下操作:

import reflect.runtime.universe._
case class TypeComparer[A](typeToCompare: TypeTag[A]){
  def unapply(universeType: Type) = universeType =:= typeToCompare.tpe
}

object TypeComparer{
  val IntComparer = new TypeComparer(typeTag[Int])
}

object TestObject{
  def tester(t: Type) {
    t match {
      case TypeComparer.IntComparer() => println("pass")
      case _ =>  println("fail")
    }
  }   

  def test[A](implicit ev: TypeTag[A]) = tester(typeOf[A])
}

你可以像以下一样运行:

TestObject.test[Int] //pass
TestObject.test[Boolean] //fail

缺点是您需要为每个比较器创建一个具体对象,因为我不知道如何使用apply中使用的类型的伴随对象

所以,它有点冗长......而if在这里可能更好。

答案 2 :(得分:-1)

好的,我找到了解决方法:

def test(t: reflect.runtime.universe.Type) {
  t.toString match {
    case "Int" => \\ ...
    case "scala.Int" => \\ ...
    case "Double" => \\ ...
    case "scala.Double" => \\ ...
    case "String" => \\ ... 
    case _ =>  \\ ...
  }
}   

但是,是否有更好的解决方案可以避免通过字符串?