Załóżmy, że mamy następujące klasy przypadek i rodzaj Alias:
scala> case class Foo[A](a: A)
defined class Foo
scala> type F = Foo[_]
defined type alias F
Możemy teraz (niezbyt skutecznie) zrobić listę rzeczy typu F
:
scala> val foos: List[F] = List(Foo(1), Foo("a"), Foo('a))
foos: List[F] = List(Foo(1), Foo(a), Foo('a))
I możemy przekształcić tablicy:
scala> foos.toArray
res0: Array[F] = Array(Foo(1), Foo(a), Foo('a))
Tak wyraźnie kompilator jest w stanie znaleźć manifeście musi jako niejawny argument do metody toArray
na List
. Ale jeśli poprosić o zwykły stary Manifest
dla F
otrzymujemy błąd:
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]
więc jest oczywiste, że kompilator ma problemy z wykorzystaniem manifesty do reprezentowania wieloznaczny w naszym typu alias.
Powodem, dla którego toArray
działa, jest oczekiwanie, że ClassManifest
, a nie tylko Manifest
. I faktycznie możemy uzyskać ClassManifest
dla F
bez żadnych problemów, właśnie dlatego, że ClassManifest
używa do reprezentowania swoich argumentów typu - w przeciwieństwie do Manifest
, których argumenty typu są po prostu inne rzeczy typu Manifest
.
scala> classManifest[F]
res2: ClassManifest[F] = Foo[<?>]
To <?>
jest reprezentacją ciąg NoManifest
. Odgrywa on tutaj rolę None
, umożliwiając kompilatorowi przedstawienie informacji o klasie o typie F
(który jest wszystkim, czego potrzebujemy do stworzenia tablicy, na szczęście), nie mówiąc nic o argumentach typu z F
poza "nie, mogę" t modelu, który ".