2011-10-05 38 views
2

基本上我想要做这样的事情:我可以使用Scala抽象方法绑定的类型,然后“收紧”子类中的定义吗?

class Shape 

class CoordSystem 
class C3D(val x: Double, y: Double, z: Double) extends CoordSystem 
class C2D(val x: Double, y: Double) extends CoordSystem 

abstract class Shape { 
    def getCoords[C <: CoordSystem]: List[C] 
} 

class Pyramid extends Shape { 
    def getCoords: List[C3D] = 
    List(new C3D(1,2,1), new C3D(1,1,1), new C3D(2,2,1), new C3D(2,1,1), new C3D(1.5,1.5,3)) 
} 
>> error: class Pyramid needs to be abstract, since method getCoords in class Shape of type [C <: CoordSystem]List[C] is not defined 

我已经看到了不同的想法上this answer了一把,但没有人似乎对这种情况相当正确的 - 因为他们似乎并没有让我在其他地方编写代码,其引用myShape.getCoords就好像它已在Shape子类中正确定义,返回CoordSystem的子类中的对象列表。

我还在Scala Lang的电子邮件列表中发现了an interesting discussion about generics,但无法将其与我的情况紧密结合。

感谢任何帮助!

回答

9

怎么是这样的:

class CoordSystem 
class C3D(val x: Double, y: Double, z: Double) extends CoordSystem 
class C2D(val x: Double, y: Double) extends CoordSystem 

trait ShapeLike[+C <: CoordSystem] { 
    def getCoords: List[C] 
} 

abstract class Shape extends ShapeLike[CoordSystem] 

class Pyramid extends Shape with ShapeLike[C3D] { 
    def getCoords: List[C3D] = 
    List(new C3D(1, 2, 1), new C3D(1, 1, 1), new C3D(2, 2, 1), new C3D(2, 1, 1), new C3D(1.5, 1.5, 3)) 
} 

当然什么也没有强迫你声明的额外的类型ShapeLike做到这一点;其目的是允许您使用Shape类型而不烦人额外的类型参数。因此,实际上题目中提到的问题的答案是:如果在超类中将类型参数定义为协变类型参数,则可以“加紧”类型参数的类型边界;相反,您可能会“放宽”逆变类型参数的类型边界。

+0

非常感谢让 - 菲利普 - 这就像一个魅力! –

2

一个类型参数是一个类型参数,超级合同要求你不要收缩合同 - 因为它不那么严格不会违反合同,虽然我认为这是不被允许的。

但是,您可以做其他事情:将类型放入类中。

class Shape 

class CoordSystem 
class C3D(val x: Double, y: Double, z: Double) extends CoordSystem 
class C2D(val x: Double, y: Double) extends CoordSystem 

abstract class Shape { 
    type C <: CoordSystem 
    def getCoords: List[C] 
} 

class Pyramid extends Shape { 
    override type C = C3D 
    def getCoords: List[C3D] = 
    List(new C3D(1,2,1), new C3D(1,1,1), new C3D(2,2,1), new C3D(2,1,1), new C3D(1.5,1.5,3)) 
} 
+0

谢谢丹尼尔 - 我想过这种方法(在另一篇文章中看过它)。但我无法弄清楚如何使用Shape和CoordSystem类型参数使它与单独的类很好地发挥作用。用Jean-Philippe的方法,我能够写出例如'Class Blah [C <:CoordSystem,S <:Shape with ShapeLike [CS]',然后使用'getCoords'在Blah方法中返回'List [C]'。我找不出类型覆盖类“内部”的等效语法。我的评论有意义吗? –

相关问题