【问题标题】:Scala nested case class self-bounding inheritanceScala 嵌套案例类自边界继承
【发布时间】:2016-01-16 17:29:31
【问题描述】:

我目前正在研究 Scala 中的 A* 实现。为了完成一个干净的结构,我想使用一个实现自界特征的嵌套案例类结构。但是,我在 Scala IDE 中实现此功能时遇到了一些问题。以下代码将无法编译:

trait A[T <: A[T]]

class B {

    case class C(int: Int) extends A[C] // A[this.C] won't work either

    def make = C(5)

}

object D {

    def foo[T <: A[T]](some: T) = {}

    val c = new B().make

    foo(c) // this does not compile

}

有什么办法可以让这个结构正常工作吗?

【问题讨论】:

标签: scala generics case-class


【解决方案1】:

不知道你为什么想要这个,但这就是它不能按原样工作的原因:

D.c 的类型是B#C。它是一个依赖路径的类型,我们不知道它属于B 的哪个实例。但是,C 扩展了A[C],这与在该上下文中说的A[this.C] 相同,它绑定到B 的特定实例。 foo 将类型参数T 视为B#C,对于某些b,这与b.C 不同。

您有两个选项可以编译。

放松AB#C的约束:

trait A[T <: A[T]]

class B {

    case class C(int: Int) extends A[B#C]

    def make = C(5)

}

object D {

    def foo[T <: A[T]](some: A[T]) = {}

    val c = new B().make

    foo(c)

}

或者处理依赖路径的类型,让c拥有b.C类型:

trait A[T <: A[T]]

class B {

    case class C(int: Int) extends A[C]

    def make = C(5)

}

object D {

    def foo[T <: A[T]](some: A[T]) = {}

    val b = new B
    val c: b.C = b.make

    foo(c)

}

【讨论】:

  • 谢谢!这解释了很多!
  • 我发现上一个示例中c 的显式类型实际上并不是必需的。我很想解释一下为什么引入中间值 val b 会改变 c 的推断类型。我知道没有b 的中间值没有名称,但它对推理的重要性。
  • 我认为没有类型推断规则的规范,所以我在那里不知所措。我只是认为在这种情况下类型推断器不够聪明,无法在一个语句中完成所有操作——类似于为什么需要像 def f(b: B)(c: b.C) 这样的柯里化参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多