Trying to implement smart constructor using case classes. Managed to override the copy
method fine, and I presume the apply
in the companion object should have done the trick, but I hit a wall when trying to pass in a BigInt
. I tried putting in def apply(value: BigInt): Option[Natural]
but then scalac
complains about conflicting symbols.
import spire.math.Integral // companion object contains implicit Integral[BigInt]
case class Natural private (value: BigInt) {
def copy(value: BigInt = this.value): Option[Natural] =
Natural.apply(value)
}
object Natural {
def apply[A](x: A)(implicit A: Integral[A]): Option[Natural] =
if (A.isPositive(x)) Some(Natural(x))
else None
}
/** In Foo.scala */
Natural(5L) // Option[Natural] = Some(Natural(5))
Natural(BigInt(5L)) // constructor Natural in class Natural cannot be accessed in object Foo
Perhaps such a thing is not possible?
Overloading is your problem here, as @jroesch points out in his answer.
A solution to this problem is to change the type of the argument of the private primary constructor so that the latter cannot conflict with the public factory method. There are various ways of doing that in Scala ... one might go like this,
case class Wrap[T](t: T) extends AnyVal
case class Natural private (value: Wrap[BigInt]) {
def copy(value: Wrap[BigInt] = this.value): Option[Natural] =
Natural(value.unwrap)
}
object Natural {
def apply[A](x: A)(implicit A: Integral[A]): Option[Natural] =
if (A.isPositive(x)) Some(Natural(Wrap(x)))
else None
}