[英]Scala case class implementation of smart constructors?
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
. 设法很好地重写了
copy
方法,并且我认为在伴随对象中的apply
应该已经完成了技巧,但是在尝试传递BigInt
时遇到了BigInt
。 I tried putting in def apply(value: BigInt): Option[Natural]
but then scalac
complains about conflicting symbols. 我尝试放入
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
Perhaps such a thing is not possible? 也许这样的事情是不可能的?
Overloading is your problem here, as @jroesch points out in his answer. @jroesch在他的回答中指出,这里的重载是您的问题。
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. 解决此问题的方法是更改私有主构造函数的参数类型,以使后者不会与public factory方法冲突。 There are various ways of doing that in Scala ... one might go like this,
在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
}
I believe that the error you are encountering is because of method overloading. 我相信您遇到的错误是由于方法重载。 When creating a case class the compiler will generate a signature of:
创建案例类时,编译器将生成以下特征的签名:
def apply(x: T): T
for a case class T in it's companion object T. So when you are invoking the method, method selection picks the most specific signature first. 因此,在调用方法时,方法选择将首先选择最具体的签名。 It attempts to invoke
Natural.apply(x: T): T
which I would hazard is also marked private transitively in the companion object. 它会尝试调用
Natural.apply(x: T): T
可能会危害的Natural.apply(x: T): T
在同伴对象中也被标记为private。 The conflicting symbols then becomes an issue, because it generates an apply(x: T): T
, and you are also defining an apply(x: T): T
. 然后,冲突的符号成为问题,因为它生成了
apply(x: T): T
,并且您还定义了apply(x: T): T
。
Your best bet is using a plain Scala class, and manually implementing the extractor pattern, hash, equality, ect. 最好的选择是使用普通的Scala类,并手动实现提取器模式,哈希,相等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.