我可以在Scala抽象方法上使用绑定类型然后“收紧”子类中的定义吗?

时间:2011-10-05 19:39:13

标签: scala types

基本上我想做这样的事情:

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,但无法将其与我的情况联系起来。

感谢任何帮助!

2 个答案:

答案 0 :(得分: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而不会烦恼额外的类型参数。

因此,实际上标题中所述问题的答案是:如果在超类中将其定义为协变类型参数,则可以“收紧”子类中类型参数的类型边界;相反,您可以“松开”逆变型参数的类型界限。

答案 1 :(得分: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))
}