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

Как я могу использовать оператор "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, но все безрезультатно. (И я действительно не хочу преобразовывать в строки: я чувствую, что важно, чтобы перехватчик компилятора переименовал / переместил классы.)

Я плотный или наткнулся на слепое пятно Скалы?

Ответы [ 4 ]

28 голосов
/ 23 августа 2011

Подробное сравнение случаев работает:

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

Конечно, будучи идентификатором в нижнем регистре, classOf в любом случае не должен работать напрямую в выражении. Тем не менее, ни один не сбежал

case `classOf`[Int]

в этом случае сработает, так что вам придется идти с if -гуардом.

20 голосов
/ 23 августа 2011

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

Обратите внимание, что вы не можете сопоставить тип (т. Е. Class [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 голосов
/ 26 мая 2015

Я столкнулся с той же проблемой, и размещение класса в «стабильном идентификаторе» было не очень практичным. Я обнаружил, что следующая лучшая вещь - это аккуратные заявления «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 голосов
/ 25 февраля 2018

Для рассмотрения наследования:

val what = c match {
  case q if classOf[Int].isAssignableFrom(q) => "int!"
  case q if classOf[Float].isAssignableFrom(q)  => "float!"
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...