[英]Upper and Lower bound on scala type
Consider the following hierarchy: 考虑以下层次结构:
class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3
I want to write a function that just accepts types C2
and C3
. 我想编写一个只接受
C2
和C3
类型的函数。 For that I thought of the following: 为此我想到了以下内容:
def f [C >: C3 <: C2](c :C) = 0
I'd expect the following behaviour 我期待以下行为
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
The problem is when calling it with C4
, which I don't want to allow, but the compiler accepts. 问题是用
C4
调用它,我不想允许,但编译器接受。 I understand that C4 <: C2
is correct and that C4
can be seen as a C3
. 我知道
C4 <: C2
是正确的, C4
可以看作是C3
。 But when specifying the bound [C >: C3 <: C2]
, I would expect the compiler to find a C
that respects both bounds at the same time, not one by one. 但是当指定绑定
[C >: C3 <: C2]
,我希望编译器找到一个同时尊重两个边界的C
,而不是一个接一个。
Question is : Is there any way to achieve what I want, and if not, is the compiler trying to avoid some inconsistency with this? 问题是:有没有办法实现我想要的,如果没有,编译器是否试图避免与此有些不一致?
Edit : from the answers I realized that my presumption is wrong. 编辑 :从答案中我意识到我的推定是错误的。
C4
always fulfills C >: C3
, so both bounds are indeed respected. C4
总是满足C >: C3
,因此两个边界确实得到了尊重。 The way to go for my use case is C3 <:< C
. 我的用例的方法是
C3 <:< C
。
Statically, yes. 静静地,是的。 It's pretty simple to impose this constraint:
施加此约束非常简单:
def f[C <: C2](c: C)(implicit ev: C3 <:< C) = 0
f(new C4)
wouldn't compile now. f(new C4)
现在不会编译。
The problem is, it's probably not possible to prohibit the following behaviour at compile time: 问题是,在编译时可能无法禁止以下行为:
val c: C3 = new C4
f(c)
Here variable c
has static type C3
, which passes any kind of typechecking by compiler, but it is actually a C4
at runtime. 这里变量
c
有静态类型C3
,它通过编译器传递任何类型的类型检查,但它在运行时实际上是C4
。
At runtime you can of course check the type using reflection or polymorphism and throw errors or return Failure(...)
or None
在运行时,您当然可以使用反射或多态检查类型并抛出错误或返回
Failure(...)
或None
I found that explanation from another stackoverflow question very helpful: 我发现另一个stackoverflow问题的解释非常有用:
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.
S>:T只是意味着如果传入的类型S等于T或其父类,则使用S。 If you pass a type that is sublevel to T then T will be used.
如果您将一个子级别的类型传递给T,那么将使用T.
So in your example all, but first should compile. 所以在你的例子中,但首先应该编译。 Following example illustrates the meaning of that: Let's redefine f:
以下示例说明了其含义:让我们重新定义f:
def f[U >: C3 <: C2](c: U) = c
and then: 接着:
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
Hope that helps. 希望有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.