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

时间:2016-01-06 07:16:26

标签: scala implicit

请考虑以下代码:

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类定义中定义的。

我需要做些什么来改变这项工作?

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

1 个答案:

答案 0 :(得分:2)

不幸的是,这是类体作为构造函数创建严重限制的情况之一。你想要达到的目标本身是不可能的。

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

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

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子类的定义,则可以重新强制执行安全性:

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无法强制执行的安全措施。