software - ¿Cómo puedo unir las clases en una declaración de "coincidencia" de Scala?
scala vs java (4)
Encontré el mismo problema y colocar la clase en un "identificador estable" no era tan práctico. Descubrí que lo mejor que se podía hacer era tener declaraciones ordenadas "si no".
Utilizando este método:
private def is[T <: AnyRef : Manifest](implicit cls: Class[_]) =
cls == manifest[T].runtimeClass
Puedo escribir:
implicit val arg = cls
if (is[ClassA]) ...
else if (is[ClassB]) ...
...
else throw new IllegalArgumentException("Unknown class: " + cls)
¿Cómo puedo usar una declaración de "coincidencia" para identificar el valor de una variable de clase? Lo siguiente no es válido y no puedo encontrar una variante aceptable, excepto si ... else if ... else ...
val c: Class[_] = classOf[Int]
val what = c match { case classOf[Int] => "int!"; case classOf[Float] => "float!" }
El compilador se queja: error: not found: type classOf
Y, por supuesto, no puedo usar Class[Int]
porque esa información de tipo se borra:
c match { case Class[Int] => "int!"; case Class[Float] => "float!" }
error: type Class of type Class does not take type parameters.
También he probado variantes como Int.class
, todo en vano. (Y realmente no quiero convertir a cadenas: creo que es importante que el compilador atrape el cambio de nombre / clases).
¿Estoy siendo denso o me he topado con un punto ciego de Scala?
La comparación de casos verbosa funciona:
val what = c match {
case q if q == classOf[Int] => "int!"
case q if q == classOf[Float] => "float!"
}
Por supuesto, al ser un identificador en minúsculas, classOf
no debería funcionar directamente en una declaración de caso de todos modos. Sin embargo, tampoco lo hace un escapado.
case `classOf`[Int]
trabaja en este caso, así que tendrás que ir con if
-guard.
Para considerar la herencia:
val what = c match {
case q if classOf[Int].isAssignableFrom(q) => "int!"
case q if classOf[Float].isAssignableFrom(q) => "float!"
}
Puede hacer coincidir los valores de clase si crea un identificador estable (es decir, un val) para ellos,
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!
Tenga en cuenta que no puede coincidir con el tipo (es decir, Clase [Int]) porque el borrado significa que las diferentes instancias de tipo de Clase [T] son indistinguibles en el tiempo de ejecución ... de ahí la siguiente advertencia
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!