Reputation: 11888
In my process of migrating an App from 2.4 to 2.5 (and getting rid of all the static references), I have done the following:
class Generic @Inject()(implicit val mat: Materializer, cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration)
{ ... }
@Singleton
class Concrete1 @Inject() (gw:Generic) { ... }
@Singleton
class Concrete2 @Inject() (gw:Generic) { ... }
To use it, I do inject Concrete1/2 with an instance of Generic. It works, but after having seen several other examples about that on the web it doesn't seem quite correct.
I am thinking about modifying it like this :
abstract class Generic(cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration)
{ ... }
@Singleton
class Concrete1(cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration)
extends Generic(cache, wsClient, configuration) { ... }
@Singleton
class Concrete2(cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration)
extends Generic(cache, wsClient, configuration) { ... }
Then in order to be able to do : @Inject() (c1:Concrete1, c2:Concrete2)
I guess I need them to be modules as defined by : https://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection#Programmatic-bindings ?
What makes more sense to do here ?
Upvotes: 3
Views: 222
Reputation: 10007
I'd actually disagree with your "doesn't seem quite correct" statement.
I'd argue that your first example more closely reflects the composition over inheritance philosophy that has become accepted as a more maintainable way to build software.
Without knowing anything about your Concrete
or Generic
classes, it's hard to say more, but I would be very surprised if the latter, inheritance-based structure, was easier to properly unit test, whereas it would be trivial to mock a Generic
and inject it to test Concrete
classes.
Other benefits:
Upvotes: 1