2012-12-16 20 views
2

我目前有:如何刪除這個額外的類型參數?

class X[+T: Numeric](val x: T) 
abstract class M[N: Numeric, T <: X[N]] { // <- I'd like to remove N. 
    def apply(x: Int): T 
    final def row = (1 to 10).map(this(_)) 
} 

我用這樣的:

class Y(x: Double, val y: Double) extends X[Double](x) 
class Z extends M[Double, Y] {   // <- So that this is simpler. 
    def apply(x: Int) = new Y(0.0, 0.0) 
} 

它的工作原理是這樣的:

object testapp { 
    // row is properly polymorphic, allowing access to Y.y 
    def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y)) 
} 

我想Z要簡單一些,這樣我可以使用M如:

class Z extends M[Y] { 
    def apply(x: Int) = new Y(0.0, 0.0) 
} 

,或者甚至更好:

class Z extends M[Double] {   // i.e. Meaning apply can return 
    def apply(x: Int) = new Y(0.0, 0.0) // any subclass of X[Double] 
} 

Here are my Gist iterations達到這一點。

回答

2

型PARAMS第三種方法VS類型成員是同時使用。

類型成員的優點是它不污染子類的簽名。如果類型成員是多餘的(即使在具體的類中),它也可以保持抽象。只有底層的類必須定義它。

import scala.collection.immutable.IndexedSeq 
    class X[+T: Numeric](val x: T) 
    abstract class M[+A: Numeric] { 
    type W <: X[A] 
    def apply(x: Int): W 
    final def row: IndexedSeq[W] = (1 to 10) map apply 
    def sumx: A = { // in terms of the underlying Numeric 
     val n = implicitly[Numeric[A]] 
     n fromInt (0 /: row)((s,w) => s + (n toInt w.x)) 
    } 
    } 

    class Y(x: Double, val y: Double) extends X[Double](x) 
    class Z extends M[Double] { 
    type W = Y 
    def apply(x: Int) = new Y(0.0, 0.0) 
    } 

    def main(args: Array[String]): Unit = (new Z).row foreach (Console println _.y) 
+0

從最直接回答問題開始。謝謝。你能爲我澄清嗎?我正在閱讀它:'type W <:X [A]'在'M'內定義了一個'W'類型,使得'W'是'X [A]'的子類型。那麼在'M'的子類型中,'W'被「覆蓋」成爲'M'子類型所需的類型? – nix

+1

隨着界限,類型W仍然是抽象的,所以當你定義它時不需要覆蓋。 (像任何其他成員一樣。)(Spec 4.3。同樣,要小心http://stackoverflow.com/a/10223364/1296806。) –

1

你並不真的需要class M這裏:

class X[+T: Numeric](val x: T) 
def row[W <: X[_]](c: => Int => W) = (1 to 10).map(c) 

class Y(x: Double, val y: Double) extends X[Double](x) 
def z = row(_ => new Y(0.0, 0.0)) 

def main(args: Array[String]): Unit = z.map(r => println(r.y)) 

如果你想保持M,你用同樣的想法:

class X[+T: Numeric](val x: T) 
abstract class M[W <: X[_]] { 
    def apply(x: Int): W 
    final def row = (1 to 10).map(this(_)) 
} 

class Y(x: Double, val y: Double) extends X[Double](x) 
class Z extends M[Y] { 
    def apply(x: Int) = new Y(0.0, 0.0) 
} 

def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y)) 
+0

感謝您的回答,但目標不是消除'M'。我想我需要它(但我正在考慮你的選擇)。這是更大解決方案的一部分。這個想法是,'M'是一個集合,它只能包含'X [T]'所包含的類型,其中'T'是'Numeric'。我創建了幾個「M」的子類來封裝不同元素的不同功能。 – nix

+0

而不是幾個子類,您可以創建幾個函數,如z。如果沒有更大的解決方案的知識,我可能會錯過一些東西,但我認爲OO封裝在這裏是開銷。 –

+0

順便說一句,我用解決方案使用M類更新了我的答案 –

相關問題