[英]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
}
但是,由于抽象类型是在Specie
类定义中定义的,因此无法编译(第5行)。
要进行这项工作,我需要更改什么?
之所以需要抽象类型,是因为我在编译时需要其参数的类型(以对typeclass模式执行隐式查找)。 基本上,我需要做这样的事情: implicitly[SomeTypeClass[Specie#T]]
,其中SomeTypeClass
是SomeTypeClass
所有子类SpecieType
实现的类型类。
不幸的是,这是作为构造函数的类主体造成严重限制的情况之一。 您要实现的目标本身是不可能的。
据我所知,主要有两种选择。 正如@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
无法自身实施的安全性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.