2013-10-19 84 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類,並手動執行提取模式,哈希,平等等。