Я бы подумал использовать комбинацию уточнения типа и Манифест .Первый позволяет отображать абстрактный тип _B
в качестве параметра типа B
, а второй дает указание компилятору Scala повторно определить тип B
( edit : статический тип из контекста вызова) как объект времени выполнения.Вот моя попытка,
trait B
trait B1 extends B
trait B2 extends B
trait U { type _B <: B }
class U1 extends U { type _B = B1 }
class Q[B: Manifest, _U <: U { type _B = B}](u: U) {
override def toString() : String = {
implicitly[Manifest[B]].toString // Manifest[B] was an implicit parameter to Q
}
}
// Four tests:
println(new Q[B1, U1](new U1) toString) // (1) prints "$line1.$read$$iw$$iw$B1"
// println(new Q[B2, U1](new U1) toString) // (2) correctly fails to compile
// println(new Q[Nothing, U1](new U1) toString)// (3) correctly fails to compile
println(new Q(new U1) toString) // (4) prints "Nothing" (why not B1?)
. Это работает в первом случае, когда заданы явные параметры типа.Во втором случае неправильно компилируется, так как U1
содержит тип B1
, а не тип B2
.Аналогично для третьего случая.По какой-то причине, однако, компилятор Scala генерирует неверный манифест в четвертом случае, даже если компилятор выводит тип B1
.Я не знаю достаточно, чтобы сказать, является ли это ошибкой, но это, конечно, удивляет меня. Кто-нибудь может объяснить, почему в случае (4) не печатается Манифест В1?