Могу ли я использовать тип, связанный с абстрактным методом Scala, а затем «ужесточить» определение в подклассе? - PullRequest
2 голосов
/ 05 октября 2011

По сути, я хочу сделать что-то вроде этого:

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

Я видел несколько разных идей по этому ответу , но ни одна из них не кажется вполне подходящей для этого случая- потому что они не позволяют мне писать код в другом месте, который ссылается на myShape.getCoords, как если бы он был правильно определен в подклассе Shape, возвращая список объектов из подкласса CoordSystem.

Я также нашел интересную дискуссию о дженериках в списке рассылки Scala Lang, но никак не мог связать его с моей ситуацией.

Любая помощь с благодарностью!

Ответы [ 2 ]

9 голосов
/ 05 октября 2011

Примерно так:

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 без раздражающих дополнительных параметров типа.

Таким образом, на самом деле ответ на ваш вопрос, как указано в заголовке: вы можете «ужесточить» границу типапараметр типа в подклассе, если он определен как ковариантный параметр типа в суперклассе;и наоборот, вы можете «ослабить» границу типа параметра контравариантного типа.

2 голосов
/ 06 октября 2011

Параметр типа является параметром типа, и контракт суперкласса требует, чтобы вы не затягивали его контракт - его менее строгие условия не нарушали бы контракт, хотя я не думаю, что он разрешен.

Однако вы можете сделать что-то еще: поместить тип в класс.

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))
}   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...