Смешивание контравариантного и ковариантного типов в Scala - PullRequest
0 голосов
/ 25 сентября 2019

Я пытаюсь построить каркас с иерархией Context с (которая содержит неизменяемые данные) и Module с, которые создают акторы, работающие с данными.Подклассы на Context включают больше данных (например, RemoteContext будет иметь информацию о том, как взаимодействовать с удаленными хостами).Существуют также Factory объекты для создания соответствующих объектов, которые являются частью данных в Context.

Я могу определить иерархию с подклассами, и это прекрасно работает.Как только все определено, объект Mediator инициализирует каждый Module, передавая контекст.

Приведенный ниже код показывает эту базовую структуру.

import java.{ util => ju}

trait Factory
trait Context[F <: Factory]

trait SomeContext[F <: Factory] extends Context[F]

trait MediatorModule[C <: Context[_ <: Factory]] {
    def loadModule(c: C)
}

trait Mediator[C <: Context[Factory]] {
    val context: C
    def getModules: ju.List[MediatorModule[_ >: C]]
    def run() = getModules.forEach(_.loadModule(context))
}

trait OtherFact extends Factory
trait OtherContext extends SomeContext[OtherFact]

class SomeModule extends MediatorModule[SomeContext[Factory]] {
    def loadModule(c: SomeContext[Factory]): Unit = { }
}
class OtherModule extends MediatorModule[OtherContext] {
    def loadModule(c: OtherContext): Unit = { }
}

class OtherContextImpl extends OtherContext {

}

class OtherMediator extends Mediator[OtherContext] {
    val context: OtherContext = new OtherContextImpl
    def getModules: ju.List[MediatorModule[_ >: OtherContext]] =
        ju.Arrays.asList(new SomeModule,
                         new OtherModule)
}

(Код был изначально написан наJava, именно поэтому он использует списки Java).

Как написано, компиляция не выполняется:

Test.scala:78:26: type mismatch;
[error]  found   : SomeModule
[error]  required: MediatorModule[_ >: OtherContext]
[error] Note: SomeContext[Factory] <: Any (and SomeModule <: MediatorModule[SomeContext[Factory]]), but trait MediatorModule is invariant in type C.
[error] You may wish to define C as +C instead. (SLS 4.5)
[error]         ju.Arrays.asList(new SomeModule,
[error]                          ^
[error] one error found

Следуя предложению компилятора, объявив trait MediatorModule[+C <: Context[_ <: Factory]], вместо этого выдает две ошибки:

Test.scala:52:20: covariant type C occurs in contravariant position in type C of value c
[error]     def loadModule(c: C)
[error]                    ^
[error] Test.scala:75:29: type arguments [OtherContext] do not conform to trait Mediator's type parameter bounds [C <: Context[Factory]]
[error] class OtherMediator extends Mediator[OtherContext] {
[error]                             ^

Я могу исправить один с trait Context[+F <: Factory], но ошибка варианта co / contra остается.

Что я могу сделать, чтобы исправить эту ошибку?Кроме того, как +C переводит обратно на Java?

1 Ответ

0 голосов
/ 25 сентября 2019

Попробуйте сделать и Context, и SomeContext ковариантными

trait Context[+F <: Factory]

trait SomeContext[+F <: Factory] extends Context[F]

Тогда код скомпилируется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...