Scala案例类实现了智能构造函数?

时间:2013-10-19 05:10:11

标签: scala case-class companion-object

尝试使用案例类实现智能构造函数。管理覆盖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

也许这样的事情不可能?

2 个答案:

答案 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类,并手动实现提取器模式,哈希,相等等。