Шаблон торта 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 из AnotherModuleImpl

Вы определяете AnotherConfig дважды - один раз в AnotherModule и снова в AnotherModuleImpl. Эти два определения признака различны и считаются несовместимыми. Тип Config определяется в терминах первого из них, но когда вы определяете MyApp, вы устанавливаете тип на последний - отсюда и ошибка.

Вы можете исправить это, удалив последнее определение AnotherConfig (как предложено @rarry) или предложив последнему признаку расширить первое (если у вас есть причины оставить последнее, например, определить дополнительные поля).

Другие вопросы по тегам