2013-05-17 93 views
1

我有一個抽象類,與採用浮動的列表作爲參數的方法:如何重載父類方法

abstract class a { 
    def m(p: List[Float]) { 
     println("Passed List[Float] to p()") 
    } 
} 

我想重載米的一個具體的繼承類:

class b extends a { 
    def m(p: List[Double]) { 
     println("Passed List[Double] to p()") 
    } 
} 

有沒有辦法做到這一點?當我嘗試它,我得到這個錯誤:

error: name clash between defined and inherited member: 
method m:(p: List[Double])Unit and 
method m:(p: List[Float])Unit in class a 
have same type after erasure: (p: List)Unit 
    def m(p: List[Double]) { 

回答

1

你必須以某種方式更改簽名,所以你需要一個虛擬的說法。

abstract class A { 
    def m(p: List[Float]) { println(p.sum) } 
} 

class B extends A { 
    def m(p: List[Double])(implicit dummy: Unit =()) { println(p.product) } 
} 

現在

scala> val b = new B 
b: B = [email protected] 

scala> { b.m(List(3.0f,3.0f)); b.m(List(3.0, 3.0)) } 
6.0 
9.0 

耶!

另一方面,這實際上可以讓事情變得不那麼方便。

scala> val a = new A {} 
a: A = [email protected] 

scala> a.m(List(3,3)) 
6.0 

scala> b.m(List(3,3)) 
<console>:11: error: overloaded method value m with alternatives: 
    (p: List[Double])(implicit dummy: Unit)Unit <and> 
    (p: List[Float])Unit 
cannot be applied to (List[Int]) 
       b.m(List(3,3)) 
       ^

不是說你會知道哪一個是正確的,b。所以這種方法可以保護您免受錯誤的影響,但代價是不會推斷正確的類型(因爲這是正確的,不明確)。

2

有針對的override關鍵字,但是在這種情況下,問題是類型擦除在編譯時。第一種方法採用List[Float],另一種採用List[Double]

這些類型將被擦除,因此您會得到兩種方法,其中List並返回Unit。這是衝突。

更改名稱

現在簡單的解決方法是給他們不同的名字。

使用泛型

abstract class a[T] { 
    def m(p: List[T]) { 
     println("Passed List[Float] to p()") 
    } 
} 

class b extends a[Double] { 
} 
+0

我不希望重寫,我想重載。所以根據參數類型可以調用m()的任一版本。 – bwroga

+0

您可以改用數組。 Scala數組直接映射到未使用泛型實現的Java數組。所以類型信息實際上在運行時停留在數組中。 – GJK

1

我不知道究竟你正在嘗試做的,但我有另一個建議你

abstract class A { 
    protected def _m(p: List[Float]) { 
    } 
} 

class B extends A { 
    def m(p: List[Double]){ 
    _m(p.map(_.toFloat)) 
    } 
} 

class C extends A { 
    def m(p: List[Float]) { 
    println("Passed List[Float] to p()") 
    _m(p) 
    } 
}