Scala - 构造函数中的抽象类型

Scala - Abstract type in constructors

考虑以下代码:

sealed trait SpecieType
case class Mammal() extends SpecieType
case class Insect() extends SpecieType

abstract class Specie(name: String, specie: T) {
  type T <: SpecieType
}

但是编译失败(第 5 行),因为抽象类型是在 Specie class 定义中定义的。

我需要更改什么才能使这项工作正常进行?

我需要一个抽象类型的原因是因为我在编译时需要它的参数类型(以对类型class 模式执行隐式查找)。基本上,我需要做这样的事情:implicitly[SomeTypeClass[Specie#T]],其中 SomeTypeClassSpecieType 的所有子 class 实现的类型 class。

不幸的是,这是 class 主体作为构造函数造成严重限制的情况之一。你想要实现的目标本身是不可能的。

据我所知,主要有两种选择。一种是,正如@cchantep 在评论中所建议的那样,使用类型参数而不是抽象类型成员。需要注意的是,它会更改 Specie 的声明,这可能会使您在程序其余部分的生活变得乏味。

另一种选择允许您以一些不安全为代价保留类型成员版本。这可能是可以接受的,因为你有一个抽象 class 无论如何,所以只有 subclasses 需要小心:

sealed abstract class Specie(name: String, _specie: SpecieType) {
  type T <: SpecieType

  val specie: T = _specie.asInstanceOf[T]
}

class MammalSpecie extends Specie("Mammal", Mammal()) {
  type T = Mammal
}

如果你能忍受丑化 Specie 的子 class 的定义,你可以 re-enforce 安全,使用中间摘要 class:

sealed abstract class Specie(name: String, _specie: SpecieType) {
  type T <: SpecieType

  val specie: T = _specie.asInstanceOf[T]
}

abstract class SpecieBase[U <: SpecieType](name: String, _specie: U)
    extends Specie(name, _specie) {
  type T = U
}

class MammalSpecie extends SpecieBase("Mammal", Mammal())

由于Specie本身是密封的,从Specie扩展的唯一方法是实际从未密封的SpecieBase扩展。 SpecieBase 强制执行 Specie 无法强制执行的安全性。