【发布时间】:2019-07-25 10:55:09
【问题描述】:
我想定义一个特征,它使用具体类的类型,在其抽象方法之一中将其扩展为返回类型。这在 Scala (2.13) 中可行吗?例如,以下内容无法编译,因为我找不到绑定ConcreteType 的方法:
trait Shape
trait Growable {
def grow() : ConcreteType
}
case class Circle(x : Int, y : Int, size : Int) extends Shape with Growable {
def grow() : Circle = this.copy(size = size + 1)
}
case class Square(x : Int, y : Int, size : Int) extends Shape with Growable {
def grow() : Square = this.copy(size = size + 1)
}
我用以下代码实现了一些接近:
trait Shape
trait Growable[T <: Shape] {
def grow() : T
}
case class Circle(x : Int, y : Int, size : Int) extends Shape with Growable[Circle] {
def grow() : Circle = this.copy(size = size + 1)
}
case class Square(x : Int, y : Int, size : Int) extends Shape with Growable[Square] {
def grow() : Square = this.copy(size = size + 1)
}
然后这个代码的用户会这样使用它:
val circle : Circle = Circle(0, 0, 10).grow()
val square : Square = Square(0, 0, 10).grow()
// or
val shapes : Seq[Shape] = List(circle, square).map(_.grow())
我想避免通过泛型传递类型,这似乎是多余的。关于如何实现这一点的任何想法?
【问题讨论】:
-
我对 “不正确” 答案的数量感到惊讶,因为这是 Scala 中非常常见的问题。 This blog post from Rob Norris详细解释问题和解决方案。 - 长话短说;博士;最简单的解决方案是使用F-Bounded 多态(与您的解决方案类似),但它并不完全安全。最好的解决方案是使用 typeclasses 而不是 subtype 多态性。 - 顺便说一句,如果你有兴趣,我写了一个简单的article 比较这两个
-
请注意,马里奥的回答包括我提到的 typeclasses 方法。
标签: scala traits type-systems