Generics 如何在Scala中混合泛型和抽象类型?

Generics 如何在Scala中混合泛型和抽象类型?,generics,scala,abstract-data-type,Generics,Scala,Abstract Data Type,我想执行以下操作,但“Iterable[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 } tra

我想执行以下操作,但“Iterable[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
}

由于
Iterable
是泛型的,因此选择泛型而不是类型成员是一种强烈的动机,至少对于EnumMeta和更高级别的成员是如此。您可以从具有类型成员的祖先到泛型,如下所示:

type EnumMeta[B <: Base] extends Meta with Iterable[B] {
  override type BASE = B
} 

另一种让代码编译的方法是使用类型投影

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
}
编译器抱怨

[error] illegal cyclic reference involving trait EnumMeta
[error]   trait EnumMeta extends Meta with Iterable[EnumMeta#BASE] {
[error]                                                      ^
这种限制是不幸的,并且是类型参数相对于类型成员的优势。请参阅以供参考


(还有第二个问题,type
MetaBase
未定义,但这与您的问题无关。)

trait Base和Meta仅在示例中为空;它们在实际代码中具有功能。我花了好几天的时间试图弄清楚编译器关于泛型基础层次结构的模糊错误消息,尽管事实上,自从泛型出现以来,我一直在Java中使用它们,而且我在不到一个小时的时间内就得到了使用抽象类型的工作等价物。因此,如果没有其他方法,我只会在Scala中再次使用泛型。这只是一张便条,如果它们是空的,就应该把它们移走。也许你可以发布一些你想要的java等价物。因此,您可以引用抽象类型作为泛型参数,但不能引用您自己的抽象类型。但是,引入另一个中间基trait/类来更改抽象类型就足够了,并且通过再次从中间类派生来缩小具有该抽象类型的Iterable[]。但是,与直接在Iterable[]中使用具体类型相比,您并没有真正获得任何好处,就像我所做的那样。至少你有选择的余地。
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] {}
}
object EnumContext extends EnumContext  {
   type BASE = EnumBase
   type META = EnumMeta
}
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
}
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]                                                      ^