我想使用Cake Pattern将某些软件系统的各个部分拆分成组件,使其完全模块化,如this article中所提出的那样。在最简单的情况下,我想要一些可模拟的组件,比如说Logging,Config,Database,Scripts等可能会互相使用。代码可能看起来像
trait AbstractConfig {
def config: AbstractConfigInterface
trait AbstractConfigInterface {
def test: Unit
}
}
trait SomeConfig extends AbstractConfig {
this: Core =>
def config = SomeConfigImplementation
object SomeConfigImplementation extends AbstractConfigInterface {
def test = println("conf.test method called")
}
}
trait AbstractDatabase {
def database: AbstractDatabaseInterface
trait AbstractDatabaseInterface {
def connect: Unit
}
}
trait SomeDatabase extends AbstractDatabase {
this: Core =>
def database = SomeDatabaseImplementation
object SomeDatabaseImplementation extends AbstractDatabaseInterface {
def connect = {
println("connect method called")
core.conf.test
}
}
}
trait Core {
this: AbstractDatabase with AbstractConfig =>
def core = CoreInterface
object CoreInterface {
def db = database
def conf = config
}
}
object app extends Core with SomeDatabase with SomeConfig
object Run {
def main(args: Array[String]) = {
app.core.db.connect
}
}
此处数据库和配置组件(SomeConfig
和SomeDatabase
特征)是可插入的,如果需要,可以更改为其他一些实现。他们的实现可以访问保存数据库和配置的core
对象,因此数据库可以在需要时访问配置,反之亦然。
所以问题是:如果像SomeDatabase
这样的特性变得很大并且不适合单个文件,那么如何将其拆分为保留对core
对象的访问的单独类?更具体地说,假设我需要将SomeDatabase
中的连接方法中的一些代码移到另一个文件中:
// SomeDatabase.scala
trait SomeDatabase extends AbstractDatabase {
this: Core =>
def database = SomeDatabaseImplementation
object SomeDatabaseImplementation extends AbstractDatabaseInterface {
def connect = {
val obj = new SomeClass()
}
}
}
// SomeClass.scala in the same package
class SomeClass {
core.conf.test // Does not compile - how to make it work??
}
SomeClass
是SomeDatabase如何工作的实现细节,所以我显然不想把它作为特性并将其混合到应用程序中。有没有办法为core
提供SomeClass
对象的访问权限?
一些相关链接:
答案 0 :(得分:2)
最简单的方法是将Core
作为构造函数参数传递给SomeClass
。
// SomeDatabase.scala
trait SomeDatabase extends AbstractDatabase {
this: Core =>
def database = SomeDatabaseImplementation
object SomeDatabaseImplementation extends AbstractDatabaseInterface {
def connect = {
val obj = new SomeClass(SomeDatabase.this) // pass it here
}
}
}
// SomeClass.scala in the same package
class SomeClass(coreComp: Core) { // use it here
coreComp.core.conf.test
}
有趣的是,我真的只想传递CoreInterface
或AbstractConfigInterface
,但事实上它们是内部类型确实很难。