I would like to have the automatic companion class apply
constructors of a case class to perform implicit conversions for me, but cannot figure out how to do so. I've searched all over and the closest answer I could find was for this question (I'll explain why it isn't what I'm looking for below).
I have a case class that looks something like this:
case class Container(a: Long, b: Long, c: Long)
I'm using the container to count instances where certain conditions apply, so I'd like to be able to have the constructor automatically convert boolean parameters to longs (if (boolean) 1L else 0L
).
The real case class, of course, has many parameters, so it would be tedious and terribly repetitive to make my own companion object and overload apply
to accept Boolean
parameters. Additionally, something like the code below isn't ideal (if it were implemented correctly somehow) as it only accepts boolean arguments:
object Container {
def apply(args: Boolean*) = {
// doesn't REALLY work since number of arguments not enforced
Container(args map { if (_) 1L else 0L } toArray: _*)
}
}
val c1 = Container(1, 0, 1) // works
val c2 = Container(true, false, true) // might be workable if done correctly
val c3 = Container(true, 0, 1) // won't work
I tried adding an implicit conversion in the companion object (below), hoping that it would automatically be used in Container.apply
, but it appears that this does not actually put the implicit conversion into the namespace of the code that calls apply.
object Container {
implicit def booleanToLong(x: Boolean): Long = if (x) 1L else 0L
}
I'm able to get things working using this hackish workaround:
{
import Container.booleanToLong
// all of these now work
val c1 = Container(1, 0, 1)
val c2 = Container(true, false, true)
val c3 = Container(true, 0, 1) // works!!!
}
The biggest problem is that I have to import booleanToLong
into the code that wants to create a Container
and thus must put it in its own block for safety (booleanToLong
is generally undesirable).
Finally, the solution of using an implicit parameter that itself includes an implicit conversion doesn't work because it would require an explicit overriding of apply
, defeating the goal of not repeating a long parameter list and marshaling types.
Is there a way to do this such that I get implicit conversions for free every time I make a Container
, but not otherwise? Or is this impossible due to some sort of technical constraint?