这是我实施Scala蛋糕模式的早期尝试之一:
trait dbConfig {
val m: Model = ???
}
trait testDB extends dbConfig {
override val m = new Model(Database.forURL("jdbc:h2:mem:testdb", driver = "org.h2.Driver"))
m.cleanDB
}
trait productionDB extends dbConfig {
override val m = new Model(Database.forURL("jdbc:postgresql:silly:productionDB", driver = "org.postgresql.Driver"))
}
trait SillySystem extends HttpService with dbConfig {
....
// System logic
....
}
这将允许我在测试时使用我的服务:
class TestService extends SillySystem with testDB {
.....
}
和生产一样:
class ProductionService extends SillySystem with productionDB {
.....
}
这有效,但我做得对吗?
答案 0 :(得分:3)
将DbConfig
摘要变为抽象并使用def
since,可以使用def
或val
来覆盖lazy val
,但不是相反。
SillySystem
is not a DbConfig
,所以使用依赖注入而不是继承。
trait DbConfig {
def m: Model // abstract
}
trait TestDB extends DbConfig {
// you can override def with val
val m = new Model(Database.forURL("jdbc:h2:mem:testdb", driver = "org.h2.Driver"))
m.cleanDB
}
trait ProductionDB extends DbConfig {
val m = new Model(Database.forURL("jdbc:postgresql:silly:productionDB", driver = "org.postgresql.Driver"))
}
trait SillySystem extends HttpService {
this: DbConfig => // self-type. SillySystem is not a DbConfig, but it can use methods of DbConfig.
....
// System logic
....
}
val testService = new SillySystem with TestDB
val productionService = new SillySystem with ProductionDB
val wrongService1 = new SillySystem // error: trait SillySystem is abstract; cannot be instantiated
val wrongService2 = new SillySystem with DbConfig // error: object creation impossible, since method m in trait DbConfig of type => Model is not defined
val correctService = new SillySystem with DbConfig { val m = new Model(...) } // correct