У меня есть головоломка с ошибкой компилятора Scala, которую я не могу понять. По причинам, не указанным здесь, мне нужно объявить свои классы, используя curiously recurring template pattern. Некоторые из моих классов должны содержать другие параметры. Например, урезанная версия моего кода выглядит так:Любопытно повторяющиеся шаблонные ограничения шаблонов с абстрактными типами Scala
trait Container[C <: Container[C]] {
def stuff: C
}
trait Aggregation {
def fill(x: Double): Unit
}
class Counted extends Container[Counted] {
def stuff = this
}
class Counting extends Container[Counting] with Aggregation {
def stuff = this
def fill(x: Double) { }
}
class Binned[V <: Container[V]](v: V) extends Container[Binned[V]] {
def stuff = this
def substuff = v
}
class Binning[V <: Container[V] with Aggregation](v: V) extends Container[Binning[V]] with Aggregation {
def stuff = this
def substuff = v
def fill(x: Double) { }
}
Вышеупомянутые работы отлично. Теперь я хочу, чтобы добавить абстрактный тип из каждой -ную друг -ed:
trait Container[C <: Container[C]] {
type Ed <: Container[Ed]
def stuff: C
}
trait Aggregation {
def fill(x: Double): Unit
}
class Counted extends Container[Counted] {
type Ed = Counted
def stuff = this
}
class Counting extends Container[Counting] with Aggregation {
type Ed = Counted
def stuff = this
def fill(x: Double) { }
}
class Binned[V <: Container[V]](v: V) extends Container[Binned[V]] {
type Ed = Binned[V]
def stuff = this
def substuff = v
}
class Binning[V <: Container[V] with Aggregation](v: V) extends Container[Binning[V]] with Aggregation {
type Ed = Binned[V#Ed]
def stuff = this
def substuff = v
def fill(x: Double) { }
}
и компилятор имеет наглость сказать мне
<console>:34: error: type arguments [V#Ed] do not conform to class Binned's type parameter bounds [V <: Container[V]]
type Ed = Binned[V#Ed]
когда Ed
явно <: Container[Ed]
для всех Containers
.
Строго говоря, тип Ed
нужен только на Containers with Aggregation
, и если я переведу его туда, я получаю ту же ошибку.
Кто-нибудь знает, как я могу заявить о своем намерении компилятору?
Спасибо, удивительный, фантастический! Я привожу себя на лоб для такого очевидного решения, хотя я согласен, что похоже, что оба должны работать. –
Стоит отметить, что 'val' в списке аргументов становится необходимым, поскольку мы не можем ссылаться на' v.Ed', когда 'v' является закрытым. В моем случае я хочу, чтобы 'v' был публичным, так что все хорошо. –
Я предлагаю спросить, почему 'V # Ed' не компилируется в списке рассылки scala-user, если вы не получите ответа на это. –