我正在学习 Scala 的清单概念,并且对如何在一些简单的情况下使用它有基本的了解。让我困惑的是什么是OptNanifest
为了NoManifest
什么?我从来没有见过然后使用。有人可以举一个需要/有用的例子吗?
(我看到 Scala 2.10 用 s 替换了Manifest
s的概念,TypeTags
但在 2.10 最终版本之前我们必须使用Manifest
s。)
我正在学习 Scala 的清单概念,并且对如何在一些简单的情况下使用它有基本的了解。让我困惑的是什么是OptNanifest
为了NoManifest
什么?我从来没有见过然后使用。有人可以举一个需要/有用的例子吗?
(我看到 Scala 2.10 用 s 替换了Manifest
s的概念,TypeTags
但在 2.10 最终版本之前我们必须使用Manifest
s。)
假设我们有以下案例类和类型别名:
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
for 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[_$1]], scala.reflect.Manifest[_$1])
manifest[F]
所以很明显,编译器在使用清单来表示我们的类型别名中的通配符时遇到了问题。
有效的原因toArray
是它期望 a ClassManifest
,而不仅仅是 a Manifest
。事实上,我们可以毫无问题地得到一个ClassManifest
for F
,正是因为ClassManifest
用于OptManifest
表示它的类型参数——不像Manifest
,它的类型参数只是其他类型的东西Manifest
。
scala> classManifest[F]
res2: ClassManifest[F] = Foo[<?>]
那<?>
是 的字符串表示NoManifest
。它在这里发挥作用None
,允许编译器表示有关类型的类信息F
(幸运的是,这是我们创建数组所需要的全部),而无需说明F
超出“不,我无法建模”的类型参数”。