Ошибка компиляции паттерна 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"))
}