1

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

也许这样的事情是不可能的?

4

2 回答 2

5

正如@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
}
于 2013-10-20T10:56:19.637 回答
2

我相信您遇到的错误是由于方法重载。创建案例类时,编译器将生成以下签名:

def apply(x: T): T 

对于它的伴随对象 T 中的案例类 T。因此,当您调用方法时,方法选择首先选择最具体的签名。它试图调用Natural.apply(x: T): T我会冒险的调用也在伴随对象中被标记为私有传递。然后,冲突的符号就会成为一个问题,因为它会生成一个apply(x: T): T,并且您还定义了一个apply(x: T): T.

你最好的选择是使用一个普通的 Scala 类,并手动实现提取器模式、哈希、相等等。

于 2013-10-19T05:34:26.703 回答