簡答:不會。您會繼承衝突成員。請看下面的代碼片段:
trait Repository {def authenticate(username: String, password: String): String}
trait UserServiceComponent {self: UserRepositoryComponent =>
val userService: UserService = new UserService
class UserService {
def authenticate(username: String, password: String): String =
repository.authenticate(username, password)
}
}
trait UserRepositoryComponent {
def repository: Repository
}
trait MongoUserRepositoryComponent extends UserRepositoryComponent {
val repository: Repository =
new Repository {def authenticate(username: String, password: String) = "MongoAuthed"}
}
trait MockUserRepositoryComponent extends UserRepositoryComponent {
val repository: Repository =
new Repository {def authenticate(username: String, password: String) = "MockAuthed"}
}
trait Application extends UserServiceComponent with MongoUserRepositoryComponent
object RealApplication extends Application
// The following will be an error: "object FakeApplication inherits conflicting members:"
object FakeApplication extends Application with MockUserRepositoryComponent
相反,有需要的行爲,定義應用這樣:
trait Application extends UserServiceComponent {self: UserRepositoryComponent =>}
object RealApplication extends Application with MongoUserRepositoryComponent
object FakeApplication extends Application with MockUserRepositoryComponent
要保持在OP給出的層次結構,則需要修改代碼,例如:
trait MongoUserRepositoryComponent extends UserRepositoryComponent {
private val _repository = new Repository {def authenticate(username: String, password: String) = "MongoAuthed"}
def repository: Repository = _repository
}
trait MockUserRepositoryComponent extends UserRepositoryComponent {
private val _repository = new Repository {def authenticate(username: String, password: String) = "MockAuthed"}
def repository: Repository = _repository
}
trait Application extends UserServiceComponent with MongoUserRepositoryComponent
object RealApplication extends Application
object FakeApplication extends Application with MockUserRepositoryComponent {
override val repository: Repository = super[MockUserRepositoryComponent].repository
}
附加private val _repository
的是必要的,這樣我們可以定義repository
作爲函數,因此它可被用作在超控。 (使用super[type]
覆蓋僅適用於函數)。
編輯:最後,cake模式的目的是開發一個層次結構,其中不需要像我提供的最後一個代碼段那樣重寫。實際上,Application
不應該存在,只有RealApplication
和FakeApplication
。 (在第二個代碼片段中,我基本上只是將UserServiceComponent
更改爲Application
)。
被編輯爲使其更「cakey」,並更類似http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/這是一個很好的參考蛋糕模式(順便說一句,在你的問題中給出的例子) –
你能檢查這個問題嗎? :) http://stackoverflow.com/questions/14532368/cake-pattern-one-component-per-implementation-or-one-component-per-trait –