Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

See http://jonasboner.com/2008/10/06/real-world-scala-dependency... for an example that's broadly similar to what I ended up doing. (The site is down right now so you might want to check google's cache)

My approach was thus: basically, define an abstract trait that specifies methods that return given dependencies. Any class that required dependencies extends this trait and is itself abstract. Then, when you want a real working instance of the class you mix in a concrete implementation of the trait. It's simple, declarative, and it got the job done. Here's an example of the pattern:

  abstract class Foo {
    def addToMe(i: Int):Int
  }

  abstract trait FooService { def foo: Foo }

  class RealFoo(j: Int) extends Foo {
    def addToMe(i: Int) = i + j
  }

  trait RealFooService extends FooService { def foo = new RealFoo(42) }

  abstract class NeedsFoo extends FooService {
    def doSomething = foo.addToMe(100)
  }

  (new NeedsFoo with RealFooService).doSomething
  // Int = 142

  class TestFoo extends Foo {
    def addToMe(i: Int) = i + 1
  }

  trait TestFooService extends FooService { def foo = new TestFoo }

  (new NeedsFoo with TestFooService).doSomething
  // Int = 101
Now, this is all done at compile-time, but it really seems to accomplish most of what the first few examples in the Guice documentation do, with similar amounts of boilerplate. Again, I'm sure this approach would fall short in many more complicated scenarios, but it gets you a hell of a lot farther than Java does in solving this problem without adding any extra frameworks. Traits are also not very difficult to reason with.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: