开发者

Can I use a type bound on a Scala abstract method and then "tighten up" the definition in a subclass?

开发者 https://www.devze.com 2023-04-11 05:02 出处:网络
Essentially I want to do something like this: class Shape class CoordSystem class C3D(val x: Double, y: Double, z: Double) extends CoordSystem

Essentially I want to do something like this:

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开发者_如何学C 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

I've seen a handful of different ideas on this answer, but none of them seem quite right for this case - because they don't seem to let me write code elsewhere which refers to myShape.getCoords as if it's been correctly defined in a Shape subclass, returning a List of objects from a subclass of CoordSystem.

I also found an interesting discussion about generics on the Scala Lang email list, but couldn't quite tie it back to my situation.

Any help gratefully appreciated!


How about something like this:

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))
}

Of course, nothing forces you to declare the extra type ShapeLike to do this; its purpose is to allow you to use the type Shape without annoying extra type parameters.

So, actually the answer to your question as stated in the title is: you may “tighten up” the type bound of a type parameter in a subclass if it is defined as a covariant type parameter in the superclass; conversely, you may “loosen” the type bound of a contravariant type parameter.


A type parameter is a type parameter, and the super class contract demands that you do not tighten its contract -- making it less strict would not violate the contract, though I don't think it is allowed.

You can do something else, however: put the type inside the class.

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号