Я пытался взломать голову вокруг этого, но я не могу найти решение этой проблемы. Кажется, я не могу правильно моделировать его в Scala.Полиморфное обновление неизменяемых классов
Допустим, у меня есть черта MyTrait
с некоторыми непреложными классами, реализующими ее.
И это выглядит примерно так:
trait MyTrait {
type Repr <: MyTrait
def substitute(original: Item, replacement: Item) : Repr
def substituteAll(
originals: List[Item],
replacement: Item
) : Repr = {
originals match {
case head :: tail => substitute(head).substituteAll(tail, replacement)
case Nil => this //this complains that this is not of type Repr
}
}
}
trait MyTrait2 { ... }
case class MyClassA(originals: List[Item])
extends MyTrait with MyTrait2 {
type Repr = MyClassA
def substitute(original: Item, replacement: Item) : MyClassA = {
//whatever code that updates the list etc.
MyClassA(newOriginals)
}
}
case class MyClassB(originals: List[Item])
extends MyTrait with MyTrait2 {
type Repr = MyClassB
def substitute(original: Item, replacement: Item) : MyClassB = {
//whatever code that updates the list etc.
MyClassB(newOriginals)
}
}
case class CompoundClass(list : List[MyTrait with MyTrait2])
extends MyTrait {
type Repr = CompoundClass
def substitute(
original: Item,
replacement: Item
) : CompoundClass =
CompoundClass(list.map(
myClass => myClass.substitute(original, replacement)
))
)
//the above complains that it is expecting
// List[MyTrait with MyTrait2]
//while in fact it is getting MyTrait2#Repr
}
Если бы я суммировать мои проблемы они будут выглядеть следующим образом:
Обновление неизменные классы по методу супер-признака должен возвращать тот же тип реализующего класса.
Супер-черта должна быть в состоянии вернуть
this
, когда имеет смысл, а не возвращать другой объект. У меня, похоже, проблема с этим.Мне нужно, чтобы передать супер-черту в функции, не зная фактического типа. Стандартный полиморфизм. Таким образом, тогда функция может вызывать методы признака без , зная конкретный конкретный тип.
Мне нужно иметь возможность использовать композицию для объединения классов в другие. (Представьте выражение, которое сделано из подвыражений). Похоже, стандартный состав, но с вышесказанным я получаю эти ошибки с
#Repr
Я первоначально попытался с помощью универсального типа в MyTrait[T]
, но это делает его невозможно передать какой-то конкретный класс я хочу. Я пытаюсь использовать абстрактные типы сейчас, и я, похоже, сталкиваюсь с той же проблемой во время компиляции. По сути, я думаю, что сейчас нет никакой разницы, я снова падаю в той же ловушке.
Что я делаю неправильно? Я смотрю на это не так?
На первый взгляд, я подозреваю, что некоторые из того, что вы хотите, не представляется возможным. Но найдите «F-Bounded Polymophism» (в Scala) для шаблона, который позволит вам выполнить ваш первый запрос: «Обновление неизменяемых классов с помощью метода супер-trait должно возвращать тот же тип реализующего класса». –
@KevinWright Да, его уточнение моего предыдущего вопроса. У меня все еще возникают трудности с моим сценарием, который более подробно, чем предыдущий, и предыдущий не работает. – jbx
@RandallSchulz Моим первым решением было использование F-Bounded Polymorphism, вот что я намеревался с помощью MyTrait [T] '. Однако я столкнулся с проблемой, что везде, где я ожидал «MyTrait» в качестве аргумента, компилятор начал ожидать какого-то типа для «[T]», и я оказался в полном беспорядке. KevinWright (в предыдущем вопросе) предположил, что вместо этого я использую элемент абстрактного типа, который, как представляется, хорошо работает в небольшом примере, однако на самом деле я даже не мог вернуть 'this' в функции, которые возвращали этот член типа из суперкласса , и передача экземпляра в качестве параметра начала получать '# Repr' – jbx