2012-12-16 19 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类更新了我的答案 –

相关问题