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]]
,其中 SomeTypeClass
是 SpecieType
的所有子 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
无法强制执行的安全性。
考虑以下代码:
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]]
,其中 SomeTypeClass
是 SpecieType
的所有子 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
无法强制执行的安全性。