为什么 Scala 在我的摘要 class 中不以相同的方式推断类型参数?
Why doesn't Scala infer type parameters the same way in my abstract class?
我定义了 2 个特征:A
和 B
。 B
扩展 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 的东西都是。
就像其他答案所说的那样,你在哪里设置约束取决于你想做什么。
我定义了 2 个特征:A
和 B
。 B
扩展 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 的东西都是。
就像其他答案所说的那样,你在哪里设置约束取决于你想做什么。