Supongamos que tenemos la siguiente clase de caso y tipo de alias:
scala> case class Foo[A](a: A)
defined class Foo
scala> type F = Foo[_]
defined type alias F
ahora podemos (no muy útil) hacer una lista de cosas del tipo F
:
scala> val foos: List[F] = List(Foo(1), Foo("a"), Foo('a))
foos: List[F] = List(Foo(1), Foo(a), Foo('a))
Y podemos convertir esto en una matriz:
scala> foos.toArray
res0: Array[F] = Array(Foo(1), Foo(a), Foo('a))
Así que está claro que el compilador es capaz de encontrar el manifiesto que necesita como un argumento implícito al método toArray
en List
. Pero si nos preguntamos por un viejo y simple Manifest
para F
, obtenemos un error:
scala> manifest[F]
<console>:11: error: overloaded method value classType with alternatives:
(prefix: scala.reflect.Manifest[_],clazz: Class[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and>
(clazz: Class[F],arg1: scala.reflect.Manifest[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and>
(clazz: Class[_])scala.reflect.Manifest[F]
cannot be applied to (java.lang.Class[Foo[_$1]], scala.reflect.Manifest[_$1])
manifest[F]
Así que está claro que el compilador está teniendo problemas para usar los manifiestos para representar el comodín en nuestra typeAlias.
El motivo toArray
funciona es que espera un ClassManifest
, no solo un Manifest
. Y de hecho podemos obtener un ClassManifest
para F
sin problemas, precisamente porque ClassManifest
usa OptManifest
para representar su tipo argumentos-a diferencia de Manifest
, cuyos tipos de argumentos son solo otras cosas del tipo Manifest
.
scala> classManifest[F]
res2: ClassManifest[F] = Foo[<?>]
Eso <?>
es la representación de cadena de NoManifest
. Juega el rol de None
aquí, permitiendo que el compilador represente la información de clase sobre el tipo F
(que es todo lo que necesitamos para crear una matriz, afortunadamente), sin decir nada sobre los argumentos de tipo de F
más allá de "no, puedo" t modelo eso ".