为什么 Scala 在我的摘要 class 中不以相同的方式推断类型参数?

Why doesn't Scala infer type parameters the same way in my abstract class?

我定义了 2 个特征:ABB 扩展 A。我还定义了一个类型参数化函数 addOne,它将 A 的任何子类型作为输入参数。我可以使用 B 的实例作为输入来调用此函数,因为 B 扩展了 A(请参阅 success)。但是,当我尝试在抽象 class 的上下文中做同样的事情时,这不再起作用了。我错过了什么?

trait A {
  val a: Int
}

trait B extends A {
  val b: Int
}

def addOne[T <: A](t: T): Int = t.a + 1

def success[U <: B](u: U): Int = addOne(u)  // this works!


abstract class C[T <: A, U <: B] {

  def addTwo(t: T): Int = t.a + 2

  def fail(u: U): Int = addTwo(u)  // this doesn't compile

}

谢谢!

这是因为,在 class C 中,虽然您知道 U 是 B 的子类型,而 T 是 A 的子类型,但您不能保证 U 是 T 的子类型。

编辑:我想我找到了一种方法来做到这一点。它使用 generalised type constraints:

abstract class C[T <: A, U <: B] {

  def addTwo(t: T): Int = t.a + 2

  def fail(u: U)(implicit ev: U <:< T): Int = addTwo(u)  // compiles

}

不过我还没有对此进行完整的测试。

我不知道 C 是什么模型,但我会说:

scala> class C[T <: A, U <: B] { def f(t: T) = t.a ; def g[X <: U with T](x: X) = f(x) }
defined class C

也就是说,你只是想说无论 T 和 U 是什么,你传递给 g 的东西都是。

就像其他答案所说的那样,你在哪里设置约束取决于你想做什么。