scala 类型的上限和下限
Upper and Lower bound on scala type
考虑以下层次结构:
class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3
我想编写一个只接受类型 C2
和 C3
的函数。为此,我想到了以下几点:
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
考虑以下层次结构:
class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3
我想编写一个只接受类型 C2
和 C3
的函数。为此,我想到了以下几点:
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