2011-08-23 6 views
17

"match"ステートメントを使用してクラス変数の値を特定するにはどうすればよいですか?以下は無効である、と私は許容バリアント見つけることができない - 場合以外... ...他にあれば、他の...Scalaの "match"ステートメントでクラスをどのように一致させることができますか?

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

はまあ、以下の答えが正しい(と回答に感謝です! )しかし、ますますスカラの醜い穴のように見える*。クラスはシングルトンなので、変数を効率的にマッチングさせるために変数を変数に代入する必要はありません。また、カスケードな一連のifを使用したり、ガードや別のステートメントとして記述したりする必要はありません。しかしそれは明らかにそうです。 – 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])ので、消去は

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

安定した識別子 - はい、私はそれを恐れていました。恐ろしいです。 "タイプに一致するクラス(Int [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文で直接動作するべきではありません。あなたはif -guardで行くことがありますので、しかし、どちらも、この場合には、エスケープ

case `classOf`[Int] 

仕事もしません。あなたが安定した識別子を作成する場合は、クラス値に一致させることができます

+0

はい、if-guardは 'case'ステートメントを' if/else'ステートメントのセットに変換します。醜い、しかし全く正しい。ありがとうございました! – Tim

+0

この質問に対する巧妙な解決策 – javadba

0

以下ので、警告が、私は同じ問題が発生したため、「安定した識別子」でクラスを配置すると、その実用的ではありませんでした...クラスの異なるタイプのインスタンス[T]は、実行時に区別できないことを意味し。私は次の最良のものが整理された '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!" 
} 
関連する問題