如何指示抽象成员将在Scala中返回具体类型

时间:2018-10-29 05:56:14

标签: scala

我经常遇到一个问题,我需要一个抽象类的实现中的成员来表示它将返回具体类型。我确定我这里缺少明显的东西。

这是一个说明问题的简单示例:

object Poop {
  def getValue[T <: Poop](x: T): T = x.aValue
}

abstract class Poop {
  val aValue: Poop
}

这显然无法使用“类型为Poop的表达式不符合预期的类型T”来编译x.aValue表达式,这显然是因为编译器不知道aValue的实际类型是什么。

如何定义我的抽象类,以便aValue将成为具体类型?还是应该像这样对问题建模?

1 个答案:

答案 0 :(得分:4)

这可以通过F-bounded polymorphism来实现:

object Poop {
  def getValue[T <: Poop[T]](x: T): T = x.aValue
}

abstract class Poop[Self <: Poop[Self]] {
  val aValue: Self

  // No need for an external method. This will return the concrete type.
  def getValue: Self = aValue
}

class Foo extends Poop[Foo] {
  val aValue: Foo = this
}

让抽象类带有类型参数并不总是很方便。在这种情况下,可以将具体类型定义为类型成员:

object Poop {
  // Helper type that provides access to the concrete type with a type parameter.
  type Aux[C <: Poop] = Poop { type Self = C }

  def getValue[T <: Poop.Aux[T]](x: T): T = x.aValue
}

abstract class Poop {
  type Self <: Poop.Aux[Self]

  val aValue: Self

  def getValue: Self = aValue
}

class Foo extends Poop {
  type Self = Foo

  val aValue: Foo = this
}