在this问题之后,我现在有以下内容:
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]")
^
这实际上是我一直在努力的错误。有人可以解释它为什么会发生吗?目前,作为解决方法,我只是在每个模块实现中显式地转换配置对象。
答案 0 :(得分:6)
你写的应该工作,但由于this bug而没有。
您可以使用多种解决方法。将type Config = PetStoreConfig with AnotherConfig
添加到模块实现中可能比铸造更不愉快。
更新:正如som-snytt在评论和回答中指出的那样,在自我类型的结尾添加with PetStoreModuleImpl
(关键不是with PetStoreModule
,这是一个更好的解决方案。< / p>
作为脚注:正如在SI-7255的评论中所讨论的那样,Dependent Object Types calculus(被设计为“Scala类型系统的新基础”)将解决这个“Scala类型系统中的基本问题”
答案 1 :(得分:3)
你可以纠缠你的自我类型以保留你想要的抽象类型成员,因为the last bound wins:
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"))
}