2011-08-23 56 views
17

如何使用“匹配”语句来识别类变量的值?以下是无效的,我无法找到一个可接受的变种 - 比如果其他...否则,如果...否则...如何在Scala“匹配”语句中匹配类?

val c: Class[_] = classOf[Int] 
val what = c match { case classOf[Int] => "int!"; case classOf[Float] => "float!" } 

编译器会抱怨:error: not found: type classOf

,当然还有,我不能使用Class[Int],因为这种类型的信息将被删除:

c match { case Class[Int] => "int!"; case Class[Float] => "float!" } 
error: type Class of type Class does not take type parameters. 

我也试着像变种Int.class,都无济于事。 (我并不想转换为字符串:我觉得让编译器捕获重命名/移动类是很重要的。)

我是密集的,还是我偶然发现了一个Scala盲点?

+1

好了,下面的答案的答案正确的(和感谢! ),但它越来越显得这是Scala中的一种丑陋的洞。类是单身人士,所以你没有理由必须将它们分配给变量以便高效地匹配它们 - 也不要诉诸使用级联的ifs,写成守卫或单独的语句。但显然是这样。 – Tim

回答

18

可以匹配类值,如果你创建一个稳定的标识符(即一个VAL)对他们来说,

scala> val c: Class[_] = classOf[Int] 
c: Class[_] = int 

scala> val ClassOfInt = classOf[Int] 
ClassOfInt: java.lang.Class[Int] = int 

scala> val ClassOfFloat = classOf[Float] 
ClassOfFloat: java.lang.Class[Float] = float 

scala> val what = c match { 
    |  case ClassOfInt => "int!" 
    |  case ClassOfFloat => "float!" 
    | } 
what: String = int! 

请注意,您不能在类型相匹配(即等级[INT]),因为擦除意味着类[T]的不同类型的实例是在运行时没有区别...因此下面

scala> val what = c match { 
    |  case _: Class[Int] => "int!" 
    |  case _: Class[Float] => "float!" 
    | } 
warning: there were 2 unchecked warnings; re-run with -unchecked for details 
what: java.lang.String = int! 
+1

稳定的标识符 - 是的,我很害怕这个问题。可怕。 “请注意,你不能匹配类型(即Class [Int])” - 是的,有问题。不过谢谢你! – Tim

+0

(我还应该注意,这个答案可能比下面的答案更有效,所以它更接近我要找的内容,再次感谢!) – Tim

+1

一个重要的注意事项:'val'的名字必须以大写字母开头。 – vpipkt

26

的详细情况相比,工作原理:

val what = c match { 
    case q if q == classOf[Int] => "int!" 
    case q if q == classOf[Float] => "float!" 
} 

当然,作为一个小写标识,classOf不应该直接在case语句反正工作。然而,同样没有在这种情况下逃脱

case `classOf`[Int] 

工作,所以你必须去与if -Guard。

+0

是的,if-guard工作...将'case'语句转换为一组'if/else'语句。丑陋,但非常正确。谢谢! – Tim

+0

这个问题的巧妙解决 – javadba

0

警告我遇到同样的问题,并把这个类在一个“稳定的识别符”是不是实际。我发现下一个最好的事情是整理'else if'陈述。

使用这种方法:

private def is[T <: AnyRef : Manifest](implicit cls: Class[_]) = 
    cls == manifest[T].runtimeClass 

我可以这样写:

implicit val arg = cls 
    if (is[ClassA]) ... 
    else if (is[ClassB]) ... 
    ... 
    else throw new IllegalArgumentException("Unknown class: " + cls) 
+0

哈哈。我只是找到了自己的答案,但我不能为此投票。 –

0

考虑继承:

val what = c match { 
    case q if classOf[Int].isAssignableFrom(q) => "int!" 
    case q if classOf[Float].isAssignableFrom(q) => "float!" 
}