【问题标题】:Upper and Lower bound on scala typescala 类型的上限和下限
【发布时间】:2015-10-15 01:08:02
【问题描述】:

考虑以下层次结构:

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 &lt;: C2 是正确的,C4 可以看作是C3。但是在指定边界[C &gt;: C3 &lt;: C2] 时,我希望编译器会找到一个同时尊重两个边界的C,而不是一个一个。

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

编辑:从答案中我意识到我的假设是错误的。 C4 总是满足 C &gt;: C3,所以这两个界限确实都得到了尊重。我的用例的方法是C3 &lt;:&lt; C

【问题讨论】:

    标签: scala types type-bounds


    【解决方案1】:

    静态地,是的。施加此约束非常简单:

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

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

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

    val c: C3 = new C4
    f(c)
    

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

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

    【讨论】:

      【解决方案2】:

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

      S >: T 仅仅意味着如果你传入一个类型 S 等于 T 或其父级,那么 S 将被使用。如果您将子级别的类型传递给 T,则将使用 T。

      所以在你的例子中,但首先应该编译。 下面的例子说明了它的含义: 让我们重新定义 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
      

      希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-19
        • 2011-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-07
        • 2020-03-29
        • 1970-01-01
        相关资源
        最近更新 更多