6

我正在学习 Scala 的清单概念,并且对如何在一些简单的情况下使用它有基本的了解。让我困惑的是什么是OptNanifest为了NoManifest什么?我从来没有见过然后使用。有人可以举一个需要/有用的例子吗?

(我看到 Scala 2.10 用 s 替换了Manifests的概念,TypeTags但在 2.10 最终版本之前我们必须使用Manifests。)

4

1 回答 1

6

假设我们有以下案例类和类型别名:

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))

很明显,编译器能够找到它需要的清单作为toArrayon 方法的隐式参数List。但是如果我们要求一个普通的旧Manifestfor 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。事实上,我们可以毫无问题地得到一个ClassManifestfor F,正是因为ClassManifest用于OptManifest表示它的类型参数——不像Manifest,它的类型参数只是其他类型的东西Manifest

scala> classManifest[F]
res2: ClassManifest[F] = Foo[<?>]

<?>是 的字符串表示NoManifest。它在这里发挥作用None,允许编译器表示有关类型的类信息F(幸运的是,这是我们创建数组所需要的全部),而无需说明F超出“不,我无法建模”的类型参数”。

于 2012-09-29T11:48:28.107 回答