Шаблон торта Scala с экзистенциальными типами: ошибка компиляции
Через этот вопрос я нашел эту статью по шаблону "config" от Precog. Я попробовал это с двумя модулями:
case class Pet(val name: String)
trait ConfigComponent {
type Config
def config: Config
}
trait Vet {
def vaccinate(pet: Pet) = {
println("Vaccinate:" + pet)
}
}
trait AnotherModule extends ConfigComponent {
type Config <: AnotherConfig
def getLastName(): String
trait AnotherConfig {
val lastName: String
}
}
trait AnotherModuleImpl extends AnotherModule {
override def getLastName(): String = config.lastName
trait AnotherConfig {
val lastName: String
}
}
trait PetStoreModule extends ConfigComponent {
type Config <: PetStoreConfig
def sell(pet: Pet): Unit
trait PetStoreConfig {
val vet: Vet
val name: String
}
}
trait PetStoreModuleImpl extends PetStoreModule {
override def sell(pet: Pet) {
println(config.name)
config.vet.vaccinate(pet)
// do some other stuff
}
}
class MyApp extends PetStoreModuleImpl with AnotherModuleImpl {
type Config = PetStoreConfig with AnotherConfig
override object config extends PetStoreConfig with AnotherConfig {
val vet = new Vet {}
val name = "MyPetStore"
val lastName = "MyLastName"
}
sell(new Pet("Fido"))
}
object Main {
def main(args: Array[String]) {
new MyApp
}
}
Тем не менее, я получаю эту ошибку компиляции:
переопределение типа Config в признаке AnotherModule с границами <: MyApp.this.AnotherConfig;
Тип Config имеет несовместимый тип
Тип Config = PetStoreConfig с AnotherConfig
Мне не понятно, почему это не должно работать (Precog также использует два компонента в их примере), есть идеи?
2 ответа
Вы определяете AnotherConfig дважды - один раз в AnotherModule и снова в AnotherModuleImpl. Эти два определения признака различны и считаются несовместимыми. Тип Config определяется в терминах первого из них, но когда вы определяете MyApp, вы устанавливаете тип на последний - отсюда и ошибка.
Вы можете исправить это, удалив последнее определение AnotherConfig (как предложено @rarry) или предложив последнему признаку расширить первое (если у вас есть причины оставить последнее, например, определить дополнительные поля).