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))
}
精彩评论