so I’ll say that I have two dependencies in my application, a connection to some subsystem pub and a connection to the database. I can do something like
trait DB {
def lookup(query:String):String
}
trait PubSub {
def subscribe(key:String, callback:String => Any)
}
then I can write my logic, for example
trait Functionality { this:DB with PubSub =>
def doSomething() {
val key = lookup("get key")
subscribe(key, data => println(data))
}
}
and then my application might be like
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()
}
and all is well and good in the world.
But what if I want to connect to two pub subsystems that use the same database implementation in the same application?
I want to do something like
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) } }
}
}
}
}
where are the objects in the second layer of the cake (implicitly?) slurp in the database implementation from the parent level.
But the scala compiler tells me
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 {
if I do the following, then do what I want
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()
}
but it's kind of dirty
I can add this feature
trait DB_Base extends DB {
private val db:DB = this
trait DB_Layer extends DB {
def lookup(query:String):String = db.lookup(query)
}
}
and then the following work
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()
}
. ? , .