请考虑以下代码:
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
的所有子类都实现。
答案 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
无法强制执行的安全措施。