簡単な答え: いいえ。競合するメンバーを継承することになります。次のコード スニペットを参照してください。
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
代わりに、目的の動作を実現するには、Application を次のように定義します。
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
して でオーバーライドとして使用できるようにするために必要FakeApplication
です。(super[type]
オーバーライドの使用は関数でのみ機能します)。
EDIT : 最後に、cake パターンの目的は、私が提供した最後のコード スニペットのようにオーバーライドする必要のない階層を開発することです。実際には、この特性はApplication
まったく存在しないはずです。(2 番目のコード スニペットでは、名前を に変更するだけです)。RealApplication
FakeApplication
UserServiceComponent
Application