我正在学习Scala的清单概念,我对如何在一些简单的情况下使用它有一个基本的了解。令我困惑的是OptNanifest
和NoManifest
是什么?我以前从未见过用过。有人可以举出他们需要/有用的例子吗?
(我看到Scala 2.10用Manifest
替换TypeTags
s的概念,但直到2.10为最终我们必须使用Manifest
s。)
答案 0 :(得分:6)
假设我们有以下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
上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[_$1]], scala.reflect.Manifest[_$1])
manifest[F]
很明显,编译器在使用清单代表我们的类别别名中的通配符时遇到了麻烦。
toArray
的工作原因是它需要ClassManifest
,而不仅仅是Manifest
。事实上,我们可以ClassManifest
获得F
毫无问题,正是因为ClassManifest
使用OptManifest
来表示其类型参数 - 与Manifest
不同,其类型参数只是Manifest
类型的其他内容。
scala> classManifest[F]
res2: ClassManifest[F] = Foo[<?>]
<?>
是NoManifest
的字符串表示形式。它在这里扮演None
的角色,允许编译器表示类型F
的类信息(幸运的是,这是我们创建数组所需的全部内容),而没有说明类型参数的任何内容。 F
超越“不,我无法模仿”。