scala - 引用类型参数的抽象类型成员

标签 scala abstract-type type-members type-projection

我的场景是这样的:

trait A {
    type B
    def foo(b: B)
}

trait C[D <: A] {
    val d: D
    def createB(): D#B
    def bar() {
        d.foo(createB)
    }
}

在 REPL 中,它会提示

<console>:24: error: type mismatch;
 found   : D#B
 required: C.this.d.B
       a.bar(createB())

这有什么问题?以及(如果可能的话)如何更正此代码?

最佳答案

D#B 是类型投影,与d.B 不同。您的类型不匹配,因为在 foo 中,B 实际上意味着 this.B,这与 D# 不同B(后者更通用)。 非正式地,您可以将 D#B 视为表示抽象类型 B 可以为 D 的任何实例采用的任何可能类型,而 d.B 是特定实例 dB 的类型。

参见 What does the `#` operator mean in Scala?What is meant by Scala's path-dependent types?对于某些上下文。

使其编译的一种方法是将 createB 的返回类型更改为 d.B:

def createB(): d.B

但是在很多情况下,这样的解决方案限制太多,因为您被绑定(bind)到特定实例 d,这可能不是您想要的。 另一种解决方案是用类型参数替换抽象类型(尽管它更冗长):

trait A[B] {
  def foo(b: B)
}

trait C[B, D <: A[B]] {
  val d: D
  def createB(): B
  def bar() {
    d.foo(createB)
  }
}

关于scala - 引用类型参数的抽象类型成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29388642/

相关文章:

scala - 如何使用gradle和IntelliJ构建Scala项目?

具有默认 null 的 Scala 按名称参数抛出 NullPointerException

eclipse - jvm/scala/lift 应用程序堆栈?

scala - 是否有像参数化类型一样的抽象类型的 list ?

scala - 为什么抽象类型的具体实现不能用于推断 ClassTag?

scala - 无法将表示类型实现为类型成员

mysql - Scala Slick 使用 InteliJ-IDE 连接到 MySQL 数据库

scala - 什么时候应该对类型成员使用访问修饰符?

Scala 抽象类型成员 - 继承和类型边界