Подтвердить что ты не робот

Как я могу сопоставлять классы в выражении Scala "match"?

Как я могу использовать оператор "match" для определения значения переменной класса? Недопустимо следующее: я не могу найти приемлемый вариант - кроме if... else if... else...

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?

4b9b3361

Ответ 1

Вы можете сопоставлять значения классов, если для них создается стабильный идентификатор (т.е. a 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!

Ответ 2

Работает подробный пример сравнения:

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.

Ответ 3

Я столкнулся с той же проблемой, и размещение класса в "стабильном идентификаторе" было не таким практичным. Я обнаружил, что лучше всего было бы иметь инструкции "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)