Инстанцирующий просмотр ограниченных типов с использованием манифестов

Я пытаюсь использовать манифесты Scala для создания экземпляра типа, и у меня возникают проблемы, когда этот тип параметризован для типов с ограниченным представлением. Я разобрал проблему до следующего кода:

class foo[X <% Ordered[X]]() {}

def boo[T](implicit m : Manifest[T]) = { m.erasure.newInstance().asInstanceOf[T] }

boo[foo[String]]

java.lang.InstantiationException: foo
    at java.lang.Class.newInstance0(Class.java:357)
    at java.lang.Class.newInstance(Class.java:325)
    . . .

Итак, вы можете видеть, что у нас есть простой класс foo, который параметризован в X; который является представлением, ограниченным Упорядоченным [X]. Функция boo просто пытается создать новый экземпляр foo[String] с помощью манифестов. Однако, когда эта функция вызывается, все идет ужасно неправильно, и я получаю трассировку стека, которая начинается, как я показал. Когда параметр типа foo не является ограниченным представлением, создание экземпляра работает без проблем. Я предполагаю, что это как-то связано с тем фактом, что граница представления является просто синтаксическим сахаром для существования неявного преобразования X => Ordered[X], и что каким-то образом зависимость манифеста от другого манифеста вызывает проблему. Однако я понятия не имею, что на самом деле происходит или, что более важно, как это исправить. Возможно ли это даже в Scala, и если нет, как люди достигают чего-то подобного?

2 ответа

Решение

newInstance работает только если T имеет конструктор без параметров. foo не имеет. Вид связан <% (так же, как контекст, связанный :) является ярлыком для неявного параметра в конструкторе.

class foo[X <% Ordered[X]] такой же как class foo(implicit freshName: X => Ordered[X]), Отсутствие конструктора без параметров для foo, newInstance выходит из строя.

Вы можете заставить его работать следующим образом:

def boo[A, B[_]](implicit toOrdA: A => Ordered[A], mf: Manifest[B[A]]): B[A] = {
  val constructor = mf.erasure.getConstructor(classOf[A => Ordered[A]])
  constructor.newInstance(toOrdA).asInstanceOf[B[A]]
}
Другие вопросы по тегам