Update: Уточнен и расширен, так как исходный вопрос был упрощен слишкомScala рекурсивных дженерик: Родительский [Ребенок] и ребенок [Родитель]
мне нужна пара признаков, каждый из которых относится к другой, что родительский и дочерний классы должны относиться друг к другу.
trait Parent [C <: Child] {
def foo(c: C)
}
trait Child [P <: Parent] {
def parent: P = ...
def bar = parent.foo(this)
}
Такое, что реализация классов должны прийти в парах:
class ActualParent extends Parent [ActualChild] {
def foo(c: ActualChild) = ...
}
class ActualChild extends Child [ActualParent] {
}
К сожалению, компилятор не любит эти черты, потому что общие типы не являются полными. Вместо C <: Child
необходимо сказать C <: Child[
что-то]
. Оставляя их неопределенные не работает либо:
trait Parent [C <: Child[_]] {
def foo(c: C)
}
trait Child [P <: Parent[_]] {
def parent: P = ...
def bar = parent.foo(this)
}
Теперь жалуется на parent.foo(this)
линии, потому что он не знает, что this
имеет правильный тип. Тип parent
должен быть Parent[this.type]
для звонка foo
, чтобы иметь нужные типы.
Я думаю, что должен быть способ обращения к собственному типу объекта? Или к типу, который требуется самому?
Update: В дополнение к @ ответ Даниила, я попытался с помощью абстрактного элемента типа внутри ребенка изложить общие типы родительского типа, как это:
trait Parent [C <: Child] {
def foo(c: C)
}
trait Child {
type P <: Parent[this.type]
def parent: P = ...
def bar = parent.foo(this)
}
Это ISN не работает, когда я пытаюсь его реализовать:
class ActualParent extends Parent [ActualChild] {
def foo(c: ActualChild) = ...
}
class ActualChild extends Child {
type P = ActualParent
}
Ошибка
overriding type Parent in trait Child with bounds >: Nothing <: Parent[ActualChild.this.type]
type Parent has incompatible type
Что это значит?
Это выглядит правильно. Теперь, как бы вы расширили это, чтобы включить цепочки родительского -> child -> child? –
Этот подход успешный, но я не очень доволен этим. Я не уверен, что могу объяснить, почему. –