我想执行以下操作,但“Iterable [BASE]”将无法编译。在保持BASE为抽象类型的同时,正确的方法是什么?
trait Base
trait Meta {
type BASE <: Base
}
trait EnumBase extends Base with Ordered[EnumBase]
trait EnumMeta extends Meta with Iterable[BASE] {
override type BASE <: EnumBase
}
trait Manager extends EnumMeta {
override type BASE <: MetaBase
}
我希望对于扩展EnumMeta并重新定义BASE的每个特征,该特征将是它自己的BASE的Iterable。到目前为止,我发现我可以这样做:
trait EnumMeta extends Meta with Iterable[EnumBase] {
override type BASE <: EnumBase
}
trait Manager extends EnumMeta with Iterable[MetaBase] {
override type BASE <: MetaBase
}
这是唯一(重复)方式,还是有更好的方法,只要它不需要返回到泛型参数?
[编辑]我刚刚发现如果泛型类型参数是自我类型,这将无效,如在Ordered [EnumBase]中。如果您尝试在名为MetaBase的派生类中更多地约束它,则得到:
illegal inheritance; self-type MetaBase does not conform to
Ordered[MetaBase]'s selftype Ordered[MetaBase]
答案 0 :(得分:1)
由于Iterable
是通用的,因此选择泛型而非类型成员具有强烈的影响力,至少对于EnumMeta及更高版本而言。您可以从具有类型成员的祖先转到这样的泛型:
type EnumMeta[B <: Base] extends Meta with Iterable[B] {
override type BASE = B
}
使用其关系涉及类型成员的几个特征,您也可以考虑将类型成员放在封闭的上下文中而不是类本身中,例如
trait Context {
type BASE <: Base
type META <: Meta
trait Base { def meta: META}
trait Meta { def base: BASE}
}
trait EnumContext extends Context {
type BASE <: EnumBase
type META <: EnumMeta
trait EnumBase extends Base with Ordered[EnumBase] {}
trait EnumMeta extends Meta with Iterable[B] {}
}
(如果在顶层,特征Base
或Meta
为空,请删除它们,只有一个抽象成员type BASE
- 和/或type META
- 没有约束条件)
当你有一个你真正想要使用的上下文时,你可以将它混合在一起,或者让一个对象扩展它。
object EnumContext extends EnumContext {
type BASE = EnumBase
type META = EnumMeta
}
答案 1 :(得分:1)
让代码编译的另一种方法是使用类型投影
trait Base
trait Meta {
type BASE <: Base
}
trait EnumBase extends Base with Ordered[EnumBase]
trait EnumMeta extends Meta with Iterable[Meta#BASE] { // Type projection!
type BASE <: EnumBase
}
trait Manager extends EnumMeta {
// override type BASE <: MetaBase // You haven't defined type MetaBase yet
}
类型投影Meta#BASE
告诉编译器你指的是BASE
。
不幸的是,自引用不起作用,
trait EnumMeta extends Meta with Iterable[EnumMeta#BASE] { ...
编译器抱怨,
[error] illegal cyclic reference involving trait EnumMeta
[error] trait EnumMeta extends Meta with Iterable[EnumMeta#BASE] {
[error] ^
这种限制很不幸,并且类型参数优于类型成员。请参阅Didierd's answer以供参考。
(还有第二个问题,类型MetaBase
未定义,但这与您的问题无关。)