Ошибка компиляции паттерна Scala с шаблоном конфигурации Precog

Исходя из этого вопроса, у меня теперь есть следующее:

case class Pet(val name: String)

trait ConfigComponent {
  type Config

  def config: Config
}

trait VetModule extends ConfigComponent {
  type Config <: VetModuleConfig

  def vet: Vet

  trait Vet {
    def vaccinate(pet: Pet)
  }

  trait VetModuleConfig {
    def extra: String
  }

}

trait VetModuleImpl extends VetModule {
  override def vet: Vet = VetImpl

  object VetImpl extends Vet {
    def vaccinate(pet: Pet) = println("Vaccinate:" + pet + " " + config.extra)
  }

}

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 PetStoreModule extends ConfigComponent {
  type Config <: PetStoreConfig

  def petStore: PetStore

  trait PetStore {
    def sell(pet: Pet): Unit
  }

  trait PetStoreConfig {
    val petStoreName: String
  }

}

trait PetStoreModuleImpl extends PetStoreModule {
  self: VetModule with AnotherModule =>
  override def petStore: PetStore = PetstoreImpl

  object PetstoreImpl extends PetStore {
    def sell(pet: Pet) {
      vet.vaccinate(pet)
      println(s"Sold $pet! [Store: ${config.petStoreName}, lastName: $getLastName]")
    }
  }
}

class MyApp extends PetStoreModuleImpl with VetModuleImpl with AnotherModuleImpl {

  type Config = PetStoreConfig with AnotherConfig

  override object config extends PetStoreConfig with AnotherConfig {
    val petStoreName = "MyPetStore"
    val lastName = "MyLastName"
  }

  petStore.sell(new Pet("Fido"))
}


object Main {
  def main(args: Array[String]) {
    new MyApp
  }
}

Я получаю следующую ошибку компиляции:

value petStoreName is not a member of PetStoreModuleImpl.this.Config
     println(s"Sold $pet! [Store: ${config.petStoreName}, lastName: $getLastName]")
                                   ^

Это на самом деле ошибка, с которой я боролся. Может кто-нибудь объяснить, почему это происходит? В настоящее время, в качестве обходного пути, я просто явно приводил объект конфигурации в каждой реализации модуля.

2 ответа

Решение

То, что вы написали, должно работать, но не работает из-за этой ошибки.

Есть несколько обходных путей, которые вы можете использовать. Добавление type Config = PetStoreConfig with AnotherConfig реализация вашего модуля, вероятно, немного менее неприятна, чем приведение.

Обновление: как som-snytt отмечает в комментарии и ответе, добавив with PetStoreModuleImpl (принципиально нет with PetStoreModule, как и следовало ожидать) до конца self-type является лучшим решением.

В качестве сноски: как обсуждалось в комментариях к SI-7255, исчисление зависимых типов объектов (которое разработано, чтобы стать "новым фундаментом для системы типов Scala") решит эту "фундаментальную проблему в системе типов Scala".

Вы можете изменить свой собственный тип, чтобы сохранить требуемый член абстрактного типа, так как победит последний ограничитель:

trait PetStoreModuleImpl extends PetStoreModule {
  self: VetModule with AnotherModule with PetStoreModuleImpl =>
  override def petStore: PetStore = PetstoreImpl

  object PetstoreImpl extends PetStore {
    def sell(pet: Pet) {
      vet.vaccinate(pet)
      println(s"Sold $pet! [Store: ${config.petStoreName}, lastName: $getLastName]")
    }
  }
}

Тогда он скажет вам, что модуль ветеринара не настроен:

class MyApp extends PetStoreModuleImpl with VetModuleImpl with AnotherModuleImpl {

  override type Config = PetStoreConfig with VetModuleConfig with AnotherConfig

  override object config extends PetStoreConfig with VetModuleConfig with AnotherConfig {
    val petStoreName = "MyPetStore"
    val lastName = "MyLastName"
    val extra = "vet-info"
  }

  petStore.sell(new Pet("Fido"))
}
Другие вопросы по тегам