Не удалось найти неявное значение для параметра доказательства типа scala.reflect.ClassManifest [T]
Кажется, я не понимаю что-то важное, возможно, об стирании (черт возьми).
У меня есть метод, который я хотел создать массив размера 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)
^
Пожалуйста, объясните, что я сделал неправильно, почему эта ошибка и какой код это делает невозможным?
Ответы
Ответ 1
Это потому, что в testArray
конкретный тип T
не известен во время компиляции. Ваша подпись должна выглядеть как def testArray[T : ClassManifest](n: Int, gen: =>T)
, это добавит к вашему методу неявный параметр типа ClassManifest[T]
, который автоматически передается вызову testArray
, а затем передается далее на вызов Array.fill
. Это называется context bound
.
Ответ 2
Метод Array.fill
имеет следующую подпись:
def fill[T](n: Int)(elem: => T)(implicit arg0: ClassManifest[T]): Array[T]
Чтобы получить экземпляр ClassManifest[T]
, вам нужно знать конкретный тип. A ClassManifest
можно получить следующим образом:
implicitly[ClassManifest[String]]
A 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 выглядит в разных областях для implicits, Ordering
обычно не указывается так. Я предлагаю вам найти неявное разрешение в Интернете, чтобы узнать больше об этом.