尝试使用案例类实现智能构造函数。管理覆盖copy
方法很好,我认为伴随对象中的apply
应该已经完成了这个技巧,但是当我试图传入BigInt
时,我碰到了一堵墙。我尝试输入def apply(value: BigInt): Option[Natural]
,然后scalac
抱怨有冲突的符号。
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
也许这样的事情不可能?
答案 0 :(得分:3)
重载是你的问题,正如@jroesch在答案中指出的那样。
此问题的解决方案是更改私有主构造函数的参数类型,以便后者不会与公共工厂方法冲突。在Scala中有各种方法可以做到这一点......有人可能会这样做,
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
}
答案 1 :(得分:2)
我相信您遇到的错误是因为方法重载。创建案例类时,编译器将生成以下签名:
def apply(x: T): T
对于它的伴随对象T中的案例类T.因此,当您调用该方法时,方法选择首先选择最具体的签名。它试图调用Natural.apply(x: T): T
,我会在同伴对象中将其标记为私有。然后,冲突的符号会成为问题,因为它会生成apply(x: T): T
,您还要定义apply(x: T): T
。
您最好的选择是使用普通的Scala类,并手动实现提取器模式,哈希,相等等。