так сказать, у меня есть две зависимости в моем приложении, подключение к некоторой подсистеме pub и подключение к базе данных. Я могу сделать что-то вродеscala take pattern - могу ли я иметь несколько слоев торта?
trait DB {
def lookup(query:String):String
}
trait PubSub {
def subscribe(key:String, callback:String => Any)
}
то я могу написать свою логику, как
trait Functionality { this:DB with PubSub =>
def doSomething() {
val key = lookup("get key")
subscribe(key, data => println(data))
}
}
, а затем мое приложение может быть как
object Awesome extends App {
object repository extends Functionality with DB with PubSub {
def lookup(query:String) = "some key"
def subscribe(key:String, callback:String => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key) ; Thread.Sleep(1000) } }
}
}
repository.doSomething()
}
и все хорошо в мире.
Но что, если я хочу подключения к двум подсистемам pub, которые используют одну и ту же реализацию базы данных в одном приложении?
Я хочу сделать что-то вроде
object Awesome2 extends App {
object repository extends DB {
def lookup(query: String): String = "some other key"
object connection1 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } }
}
}
object connection2 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } }
}
}
}
}
где объекты во втором слое пирога (неявно?) Чавкать в реализации БД от родительского уровня.
Но Скала компилятор говорит мне
error: object creation impossible, since method lookup in trait DB of type (query:String) String is not defined
object connection2 extends Functionality with PubSub with DB {
, если я делаю следующее, то это то, что я хочу
object Awesome3 extends App {
object repository extends DB {
override def lookup(query: String): String = "some other key"
object connection1 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } }
}
def lookup(query: String): String = repository.lookup(query)
}
object connection2 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } }
}
def lookup(query: String): String = repository.lookup(query)
}
}
repository.connection1.doSomething()
repository.connection2.doSomething()
}
, но это своего рода грязный
я могу добавить эту особенность
trait DB_Base extends DB {
private val db:DB = this
trait DB_Layer extends DB {
def lookup(query:String):String = db.lookup(query)
}
}
, а затем следующие работы
object Awesome4 extends App {
object repository extends DB_Base {
override def lookup(query: String): String = "some other key"
object connection1 extends Functionality with PubSub with DB_Layer {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } }
}
}
object connection2 extends Functionality with PubSub with DB_Layer {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } }
}
}
}
repository.connection1.doSomething()
repository.connection2.doSomething()
}
так что теперь у меня есть два слоя. Как мне получить три? Я чувствую, что теряю сюжет.
Торт с высоким содержанием калорий и обладает высокой гликемической нагрузкой ... и вы когда-нибудь смотрели на список ингредиентов в слоистом пироге? Предпочитают простые, натуральные продукты. То есть, у вас есть однослойный пирог, и используйте def, чтобы указать на любые ресурсы, которые вам нужны, которые в противном случае нуждались в том, чтобы их запечатали. (Это комментарий, потому что на самом деле это не решение вашей проблемы, а просто предложение о том, что он будет громоздким.) Отбрасывание 'extends DB_Base' и добавление' {dbbase => 'и удаление' с помощью DB_Layer' и добавление 'def dbLayer = dbbase' или somesuch дает явную, но компактную альтернативу. –
спасибо rex. Я смущен вашим комментарием. во-первых, что делает '{dbbase =>' точно? Я не знаком с этим синтаксисом. и во-вторых, не будет ли результат выглядеть ужасно много, как 'Awesome3'? – dvmlls
@RexKerr прав, но я не вижу, как вы можете качать свой собственный торт DI (как представляется, делает OP) без дополнительных слоев. Например, скажем, вы хотите испечь какой-то торт DAO. Вам потребуется обработать соединение с базой данных (производство, этап, тест), тип соединения (JNDI, JDBC) и сам договор DAO для внедрения DAO. Как мы можем видеть, что представляет собой ОП, картина становится сложной, что приводит к большой царапине головы ;-) Опять же, не уверен, как вы можете делать Cake DI в Scala, не опуская кроличью нору – virtualeyes