【问题标题】:View bound not compatible with upper type bound?视图边界与上限类型边界不兼容?
【发布时间】:2011-08-27 22:47:27
【问题描述】:

我有一个方法,它接受一个 Comparable 并返回一个 Comparable 并包装另一个做同样事情的方法:

def myMethod[T <: Comparable[T]](arg: T): T = otherMethod(arg)
def otherMethod[T <: Comparable[T]](arg: T): T = arg

这可以编译,但不允许我使用 Int 或任何其他需要隐式转换来实现 Comparable 的类型调用 myMethod。据我了解,视图边界旨在解决此类问题,但使用视图边界

def myMethod[T <% Comparable[T]](arg: T): T = otherMethod(arg)

我得到编译器错误:

推断的类型参数 [T] 不符合方法 otherMethod 的类型参数边界 [T <: java.lang.comparable>

到目前为止,我想出的唯一解决方法是使用第二个类型参数并在两者之间进行转换:

def myMethod[T <% Comparable[T], U <: Comparable[U]](arg: T): T =
  otherMethod(arg.asInstanceOf[U]).asInstanceOf[T]

这行得通,但它很难看。有没有更好的办法?

【问题讨论】:

    标签: scala


    【解决方案1】:

    以下任何一个都可以吗?

    1. 使T的视图绑定在两种方法中保持一致,

      def otherMethod[T <% Comparable[T]](arg: T): T = arg
      def myMethod[T <% Comparable[T]](arg: T): T = otherMethod(arg)
      
    2. 引入一个新的类型参数U &lt;: Comparable[U]和一个从TU的隐式转换,

      def otherMethod[T <: Comparable[T]](arg: T): T = arg
      def myMethod[U <: Comparable[U], T <% U](arg: T): U = otherMethod(arg)
      

    您的版本的问题是T &lt;% Comparable[T]T 转换为Comparable[T] 类型,但这不满足otherMethod 期望的递归类型T &lt;: Comparable[T &lt;: Comparable[T &lt;: ...]]伪代码)。


    更新。要将otherMethodmyMethod 与Scala 的Int 一起使用,您需要稍微帮助类型推断器,

    myMethod(2)                    // Int value types don't implement Comparable
    myMethod(2: java.lang.Integer) // Apply implicit conversion (Int => java.lang.Integer)
    

    更新 2。在 cmets 中,您说您愿意让 myMethod 变得更丑一点,以改进调用站点的类型推断。这是一个方法,

    def myMethod[U <: Comparable[U], T](arg: T)
         (implicit ev1: T => U, ev2: T => Comparable[U]): U = otherMethod(arg)
    myMethod(2) // returns java.lang.Integer(2)
    

    诀窍是使用两个隐式转换:ev1 实际上被应用,ev2 仅用于帮助类型推断。后者要求 Scala 搜索其隐式以查找 Int =&gt; Comparable[U] 类型的转换。在这种情况下,只能找到一个这样的转换,它修复了U = java.lang.Integer

    顺便说一句,试着用scalac -Xprint:typer 编译这段代码。您会看到,ev1ev2 参数都使用了相同的隐式 Predef.int2Integer

    旁注:最好避免使用 asInstanceOf 强制转换,因为它们破坏了 Scala 类型系统的健全性。

    【讨论】:

    • 1.不,不幸的是 otherMethod 是在第三方库中定义的。 2. 是的!这似乎有效。谢谢!
    • 实际上,我说得太早了……第二个解决方案确实编译了,但我仍然不能用 Int 调用它。这是错误:“类型参数 [Int,Int] 不符合方法 myMethod 的类型参数范围 [U <: java.lang.comparable>
    • 第三方库中定义的otherMethod不是也有问题吗?我收到与otherMethod(2) 相同的错误。
    • 是的,我不能用 Int 直接调用 otherMethod。这就是我希望包装器方法为我处理的部分内容:)
    • 我宁愿在调用 myMethod 时不必指定 java.lang.Integer。如果非要丑,最好封装在myMethod中。
    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    相关资源
    最近更新 更多