【问题标题】:F-bound polymorphism in Scala: concrete subclass not recognized as subtype of generic classScala中的F绑定多态性:具体子类不被识别为泛型类的子类型
【发布时间】:2013-10-23 15:43:20
【问题描述】:

我有一个泛型类型:

trait BaseTrait[T <: BaseTrait[T]] {
  self: T =>
  def similar(that: T): Float

}

具体类型:

class MyConcrete(val..) extends BaseTrait[MyConcrete]  {
  type Self = MyConcrete
..
  def similar(that: MyConcrete) = {
     return 0.5f // dummy
  }
}

我想写这样的东西:

def create[T <: BaseTrait[T]](..): T = new MyConcrete(..)

我得到错误:

type mismatch;  found: MyConcrete  required: T  

我期待由于 MyConcrete 是 BaseTrait 的子类型,它会起作用(但我错了)

我的意图是隐藏 MyConcrete 的构造,以便我以后可以将上面的内容更改为 MyConcrete2(它也像 MyConcrete 一样扩展 BaseTrait),并且我只关心 BaseTrait 接口的代码不会受到我的更改的影响。

我的create方法的接口怎么写。

谢谢。

【问题讨论】:

  • 自类型注释约束具体(可实例化)子类型的类型,但除非明确混入,否则该约束不会成为特征或其子类型的外部类型的一部分。

标签: scala generics polymorphism


【解决方案1】:
def create[T <: BaseTrait[T]](..): T = new MyConcrete(..)

那个类型参数T没有多大意义。您要求 调用者 告诉方法 T 是什么,这显然在这种情况下不起作用。如果您将T 解释为从方法返回的东西(自动推断),那么调用者仍然无法使用它。

从调用者的角度来看,你能得到的最好的结果是

def create(..): BaseTrait[_] = new MyConcrete(..)

另一方面,如果您想要一个特定的子类型但隐藏MyConcrete 的实现,您将定义一个特征

trait ConcreteLike extends BaseTrait[ConcreteLike]

class MyConcrete extends ConcreteLike {
  def similar(that: ConcreteLike) = 0.5f
}

def create(): ConcreteLike = new MyConcrete()

【讨论】:

  • 我刚刚从create方法中删除了返回值:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-14
  • 1970-01-01
  • 2013-01-26
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
  • 1970-01-01
相关资源
最近更新 更多