scala 类型的上限和下限

Upper and Lower bound on scala type

考虑以下层次结构:

class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3

我想编写一个只接受类型 C2C3 的函数。为此,我想到了以下几点:

 def f [C >: C3 <: C2](c :C) = 0

我预计会有以下行为

f(new C1)  //doesn't compile, ok
f(new C2)  //compiles, ok
f(new C3)  //compiles, ok
f(new C4)  // !!! Compiles, and it shouldn't 

问题是用 C4 调用它时,我不想允许,但编译器接受了。我明白 C4 <: C2 是正确的,C4 可以看作是 C3。但是当指定边界 [C >: C3 <: C2] 时,我希望编译器找到一个同时遵守两个边界的 C,而不是一个一个地。

问题是:有没有办法实现我想要的,如果没有,编译器是否试图避免与此不一致?

编辑:从回答中我意识到我的推定是错误的。 C4 总是满足 C >: C3,所以这两个边界确实得到了尊重。我的用例的方法是 C3 <:< C.

我发现 another Whosebug question 的解释很有帮助:

S >: T simply means that if you pass in a type S that is equal to T or its parent, then S will be used. If you pass a type that is sublevel to T then T will be used.

所以在你的例子中所有,但首先应该编译。 以下示例说明了其含义: 让我们重新定义 f:

def f[U >: C3 <: C2](c: U) = c

然后:

 val a2 = f(new C2)
 val a3 = f(new C3) 
 val a4 = f(new C4) 
 List[C2](a2, a3, a4)  //compiles
 List[C3](a3, a4)  //compiles
 List[C4](a4)  //does not cause a4 is C3

希望对您有所帮助。

静态的,是的。施加这个约束非常简单:

def f[C <: C2](c: C)(implicit ev: C3 <:< C) = 0

f(new C4) 现在无法编译。

问题是,可能无法在编译时禁止以下行为:

val c: C3 = new C4
f(c)

这里的变量c是静态类型C3,可以通过编译器的任何类型检查,但在运行时实际上是C4

在运行时,您当然可以使用反射或多态性检查类型并抛出错误或 return Failure(...)None