Для чего нужны Scala OptManifest и NoManifest?
Я изучаю концепцию манифестов Scala, и у меня есть базовое понимание того, как использовать ее в некоторых простых случаях. Меня озадачивает, что OptNanifest
и NoManifest
для чего? Я никогда не видел, чтобы его использовали. Может ли кто-нибудь привести пример, где они нужны/полезны?
(Я вижу, что Scala 2.10 заменяет понятие Manifest
С TypeTags
но до 2.10 окончательно мы должны использовать Manifest
s.)
1 ответов
предположим, что у нас есть следующий класс case и псевдоним типа:
scala> case class Foo[A](a: A)
defined class Foo
scala> type F = Foo[_]
defined type alias F
теперь мы можем (не очень полезно) составить список вещей, типа F
:
scala> val foos: List[F] = List(Foo(1), Foo("a"), Foo('a))
foos: List[F] = List(Foo(1), Foo(a), Foo('a))
и мы можем превратить это в массив:
scala> foos.toArray
res0: Array[F] = Array(Foo(1), Foo(a), Foo('a))
так ясно, что компилятор может найти манифест, который ему нужен в качестве неявного аргумента для toArray
метод on List
. Но если мы попросим простой старый Manifest
на F
, мы получаем ошибку:
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[_]], scala.reflect.Manifest[_])
manifest[F]
так что ясно что компилятор испытывает проблемы с использованием манифестов для представления подстановочного знака в нашем псевдониме типа.
причина toArray
работает то, что он ожидает ClassManifest
, а не просто Manifest
. И на самом деле мы можем получить ClassManifest
на F
без проблем, именно потому, что ClassManifest
использует OptManifest
для представления аргументов типа-в отличие от Manifest
, чьи аргументы типа - это просто другие вещи типа Manifest
.
scala> classManifest[F]
res2: ClassManifest[F] = Foo[<?>]
это <?>
строковое представление NoManifest
. Он играет роль None
здесь, позволяя компилятору представлять информацию класса о типе F
(это все, что нам нужно для создания массива, к счастью), ничего не говоря о типе доводы F
за "Нет, я не модель".