简体   繁体   English

scala类型的上限和下限

[英]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 . 我想编写一个只接受C2C3类型的函数。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM