我似乎并不了解一些重要的事情,也许是关于擦除(该死的)。
我有一个方法,我希望创建一个大小为n
的数组,其中填充了gen
的值:
def testArray[T](n: Int, gen: =>T) {
val arr = Array.fill(n)(gen)
...
}
并使用它,例如:
testArray(10, util.Random.nextInt(10))
但我得到错误:
scala: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]
val arr = Array.fill(n)(gen)
^
请解释我做错了什么,为什么会出现这个错误,以及什么样的代码不可能?
答案 0 :(得分:13)
这是因为在testArray
中,T
的具体类型在编译时是未知的。您的签名必须看起来像def testArray[T : ClassManifest](n: Int, gen: =>T)
,这将为您的方法添加类型为ClassManifest[T]
的隐式参数,该参数会自动传递给testArray
的调用,然后再传递给{{ 1}}打电话。这称为Array.fill
。
答案 1 :(得分:4)
Array.fill
方法具有以下签名:
def fill[T](n: Int)(elem: => T)(implicit arg0: ClassManifest[T]): Array[T]
为了获得ClassManifest[T]
的实例,您需要知道具体类型。可以像这样获得ClassManifest
:
implicitly[ClassManifest[String]]
每个具体类型都隐式可以使用ClassManifest
。
对于任何implicit
错误,您可以使用type参数向方法添加所需的含义:
def wrap[T](n:Int)(elem: => T)(implicit c:ClassManifest[T], o:Ordering[T])
如果您没有自己介绍ClassManifest
或Ordering
,那么图书馆的作者(很可能)会为您提供合理的默认设置。
如果您要调用wrap
方法:
wrap(2)(3)
它的扩展如下:
wrap[Int](2)(3)(implicitly[ClassManifest[Int]], implicitly[Ordering[Int]])
如果您在此处引入了自定义类Person
,则在找不到Ordering[Person]
的隐式实例时会出错。图书馆的作者无法知道如何订购Person
。你可以这样解决:
class Person
implicit val o = new Ordering[Person] { // implement required methods }
wrap(2)(new Person)
Scala编译器在不同的范围内查找含义,Ordering
通常不会像这样指定。我建议你在互联网上查找隐式解决方案,以了解更多信息。