Chi*_*rlo 4 types scala type-bounds
考虑以下层次结构:
class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3
Run Code Online (Sandbox Code Playgroud)
我想编写一个只接受类型C2和函数的函数C3.为此我想到了以下内容:
def f [C >: C3 <: C2](c :C) = 0
Run Code Online (Sandbox Code Playgroud)
我期待以下行为
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
Run Code Online (Sandbox Code Playgroud)
问题是在调用它时C4,我不想允许,但编译器接受.我明白这C4 <: C2是正确的,C4可以看作是一个C3.但是在指定边界时[C >: C3 <: C2],我希望编译器能够找到一个C同时尊重两个边界的东西,而不是一个接一个.
问题是:有没有办法实现我想要的,如果没有,编译器是否试图避免与此有些不一致?
编辑:从答案中我意识到我的推定是错误的.C4永远满足C >: C3,所以两个界限确实得到尊重.我的用例的方法是C3 <:< C.
Kol*_*mar 11
静静地,是的.施加此约束非常简单:
def f[C <: C2](c: C)(implicit ev: C3 <:< C) = 0
Run Code Online (Sandbox Code Playgroud)
f(new C4) 现在不会编译.
问题是,在编译时可能无法禁止以下行为:
val c: C3 = new C4
f(c)
Run Code Online (Sandbox Code Playgroud)
这里的变量c有静态类型C3,它通过编译器传递任何类型的类型检查,但它实际上是C4在运行时.
在运行时,您当然可以使用反射或多态检查类型并抛出错误或返回Failure(...)或None
我发现另一个stackoverflow问题的解释非常有用:
S>:T只是意味着如果传入的类型S等于T或其父类,则使用S.如果您将一个子级别的类型传递给T,那么将使用T.
所以在你的例子中,但首先应该编译.以下示例说明了其含义:让我们重新定义f:
def f[U >: C3 <: C2](c: U) = c
Run Code Online (Sandbox Code Playgroud)
然后:
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
Run Code Online (Sandbox Code Playgroud)
希望有所帮助.
| 归档时间: |
|
| 查看次数: |
529 次 |
| 最近记录: |