2013-10-19 86 views
1

试图使用案例类实现智能构造函数。管理覆盖copy法测得的,而且我相信在应该做的伎俩伴侣对象apply,而是试图在BigInt传递时,我碰了壁。我试图把在def apply(value: BigInt): Option[Natural]但随后scalac抱怨冲突的符号。斯卡拉智能构造函数的case类实现?

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 

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

回答

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 
} 
2

我相信你所遇到的错误是因为方法重载的。当创建一个类的情况下,编译器将生成的签名:

def apply(x: T): T 

的情况下,T类在它的同伴对象T.所以,当你调用的方法,方法的选择首先挑选最具体的签名。它试图调用Natural.apply(x: T): T,我将危害也在同伴对象中传递标记为私人。该冲突的符号,然后成为一个问题,因为它产生的apply(x: T): T,你也定义apply(x: T): T

最好的办法是使用一个普通的Scala类,并手动执行提取模式,哈希,平等等。