Re: Dependency injection in Scala?
On 2008-02-01 19:18:53 Stepan Koltsov wrote:
> Hello,
>
> Is there any way to write code in Scala as in Java+Spring? I. e. with
> dependency injection of components.
>
> It is hard to write large applications without DI.
>
> Should DI be done in pure Scala some way, or there is any framework,
> or Spring itself should be used?
The code below (using the example from David's link) is a way to very
closely model Spring-style autowiring using pure, immutable, type-safe
Scala. I should say that I'm not necessarily recommending this style;
there are a great many ways to skin this cat. For example the Cake
pattern uses mixins to combine all the components into a single
namespace.
First define the services, exactly as usual:
trait OnOffDevice {
def on() : Unit
def off() : Unit
}
trait SensorDevice {
def isCoffeePresent : Boolean
}
class Heater extends OnOffDevice {
def on() {}
def off() {}
}
class PotSensor extends SensorDevice {
def isCoffeePresent = true
}
Now the consumer. The dependencies are defined as a nested trait with
an abstract instance. You could import it if you like, to avoid
writing env.foo each time.
abstract class Warmer {
trait Env {
val potSensor : SensorDevice
val heater : OnOffDevice
}
protected val env : Env
def trigger() {
if(env.potSensor.isCoffeePresent) env.heater.on()
else env.heater.off()
}
}
To build a configuration, we instantiate the objects:
val thePotSensor = new PotSensor
val theHeater = new Heater
val theWarmer = new Warmer { protected val env = new Config with Env }
And name them, so that they will be wired together:
class Config {
lazy val potSensor = thePotSensor
lazy val heater = theHeater
}
The trick is the 'new Config with Env', which allows us to take a
single global Config class, and make it implement whatever Env each
component requests. That's the bit you can't do in Java. Another
possibility would be to use structural subtyping, which would save a
few keystrokes for a slight performance hit.
/J