2011-08-23 62 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!" 
}