2011-09-03 70 views
2

我嘗試在類型A已經固定Int一個子類覆蓋此方法如果通用類型已經修復,如何用隱式參數覆蓋泛型方法?

def sum[B >: A](implicit num: Numeric[B]): B = ... 

我已經嘗試過

override def sum: Int = ... 

但這並不覆蓋,當然,導致了不同的方法解析基於在運行時動態類型。

進一步說,

def sum[B >: Int](implicit num: Numeric[B]): Int 

不覆蓋,而

def sum[B >: Int](implicit num: Numeric[Int]): Int 

不,還有

def sum(implicit num: Numeric[Int]): Int 

爲什麼是這樣呢?是否有可能擺脫多餘的限制B

我不確定哪些類型和implicits我可以省略和什麼必須留,以便該方法仍然覆蓋。

回答

2

好吧,試圖解釋爲什麼規則必須迫使你保持簽名與隱含參數和方差。首先,一個不明確的參數仍然是一個參數,它可以被明確地傳遞,除了可能當它有一個單例類型(這不會很有用)時,它的幾個不同的實例是可能的。

假設我創建

case class ZModulo(val p: Int) extends Numeric[Int] { 
    def plus(a: Int, b: Int) = (a+b) % p 
    // others along the same line 
} 

這似乎是一個合適的NumericNumeric文檔沒有說明哪些法律應該預期,但ZModulo並非不合理。

現在有你的

class Summable[A] { 
    def sum[B >: A](implicit num: Numeric[A]): B =... 
} 

如果我有val ints : Summable[Int],我當然可以調用ints.Sum(ZModulo(3))。所以如果你的班級是Summable[Int]的子類,它必須允許我這樣做。所以你不能刪除Numeric參數。

其次,假設我來一個Numeric[Any]。不知道我該如何合理地爲數字做,但規範和編譯器不知道。無論如何,他們也必須接受不合理的實施。因此,讓我們

object MixThemAll : Numeric[A] {...} 

於累加簽名允許ints.sum(MixThemAll)。所以你的子類也必須允許。

因此,讓您刪除子類中的隱式參數或方差將是不健全的。

+0

的確如此。我覺得有趣的是,即使情況很好(在我的答案中,類別'C2擴展了C1'和'D2擴展了D1'),它仍然是*非法改變簽名。 –

+0

在D上,我認爲你是對的,原因是它會使超載的規則變得糟糕。在C上,我不知道。你甚至可以考慮一個通用結果被非泛型下界替代。但是,編寫泛型參數沒有不良後果。所以也許它不配有一個特別的規則來允許這樣做? –

3

第一個問題是重寫的方法需要相同數量和類型的參數,即使它們未被使用。例如,

class C1 { 
    def f[B] = println("hello") 
} 

class C2 extends C1 { 
    override def f = println("world") // Error: f overrides nothing (needs parameter B) 
} 

除此之外,還有還有,因爲Numeric[A]與健全的一個問題是在A不變。這意味着只要BC不同,就不存在Numeric[B]Numeric[C]之間的子類型關係。

想象Numeric是一個適當的方差的特點,它仍然不會工作;顯然,中覆蓋的方法簽名必須是完全一樣的:

class D1 { 
    def g(x: Int) {} 
} 

class D2 extends D1 { 
    override def g(x: Any) {} // Error: g overrides nothing (different parameter type) 
} 

我不知道爲什麼重載方法的類型不能被擴大。 編輯:原因或許是超載的兼容性,如

class D1 { 
    def g(x: Any) {} 
    def g(x: Int) {} // This is legal, even though the definitions seem to overlap 
} 

總之,當你重寫,必須保留方法的簽名,包括類型參數。在你的情況,這是你能做的最好的:

override def sum[B >: Int](implicit num: Numeric[B]): B = ... 
+0

那麼我的方法應該如何呢? – soc

+0

你需要編譯的版本是關於你能做的最好的版本。 –

相關問題