macwire
macwire copied to clipboard
Support companion object factory method
Sometimes you want to perform some validation before constructing an object. A good place for that is the method factory on the companion object:
class ParamsNeedValidation private(param1: Param1, param2: Param2)
object ParamsNeedValidation {
def apply(param1: Param1, param2: Param2) : ParamsNeedValidation = {
// validate param1 & param2
new ParamsNeedValidation(param1, param2)
}
}
When the primary constructor is found to be private, macwire could give the companion object a chance and IF it has a single apply method, try it.
So we would end up with this:
lazy val pnv = wire[ParamsNeedValidation]
Turned into
lazy val pnv = ParamsNeedValidation(param1, param2)
If the companion object has more than one apply method, a compilation error is returned:
ParamsNeedValidation constructor is private and its companion object has more than one apply method:
- apply(param1, param2)
- apply(param3)
If the companion object has no apply method, then we would fail with the usual:
ParamsNeedValidation constructor is private
This should also prove useful when you want to expose some of the inner parts of your object for testing:
package complex
// primary constructor is package private for testing as we want to play around with inner part 1 & 2
class ComplexService private[complex](innerPart1: IP1, innerPart2: IP2, other: Other) { /* ... */ }
object ComplexService {
def apply(other: Other): ComplexService = {
new ComplexService(new InnerPart1Impl, new InnerPart2Impl, other)
}
}
+1 A good rule might be to try to locate a unique publicly accessible way to constructor the object - either using a constructor or an apply method, with the appropriate return type
Yep, secondary constructors could be evaluated too - as long as they are unique, as you said.
TypeApi.companion does not seem to work? I've asked on scala-user (https://gitter.im/scala/scala/scala-user?at=55f6b30c8cc5f90a4fb6bf55) but so far no answer...
Hmm no idea I've never tried it, but it sometimes does happen that things don't work in macro-land :)