我有一个方法,它接受一个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的类型参数bounds [T&lt;:java.lang.Comparable [T]]
到目前为止,我提出的唯一解决方法是使用第二个类型参数并在两者之间进行投射:
def myMethod[T <% Comparable[T], U <: Comparable[U]](arg: T): T =
otherMethod(arg.asInstanceOf[U]).asInstanceOf[T]
这很有效,但很难看。还有更好的方法吗?
答案 0 :(得分:6)
以下任何一项都有效吗?
使T
的视图在两种方法中都保持一致,
def otherMethod[T <% Comparable[T]](arg: T): T = arg
def myMethod[T <% Comparable[T]](arg: T): T = otherMethod(arg)
引入新的类型参数U <: Comparable[U]
以及从T
到U
的隐式转换,
def otherMethod[T <: Comparable[T]](arg: T): T = arg
def myMethod[U <: Comparable[U], T <% U](arg: T): U = otherMethod(arg)
您的版本存在的问题是T <% Comparable[T]
将T
转换为Comparable[T]
类型,但这不符合递归类型T <: Comparable[T <: Comparable[T <: ...]]
(伪代码)otherMethod
期望。
更新。要在Scala otherMethod
中使用myMethod
或Int
,您需要稍微帮助类型推理器,
myMethod(2) // Int value types don't implement Comparable
myMethod(2: java.lang.Integer) // Apply implicit conversion (Int => java.lang.Integer)
更新2 。在评论中,您说您愿意让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 => Comparable[U]
类型的转换。在这种情况下,只能找到一个这样的转换,它修复了U = java.lang.Integer
。
顺便说一句,尝试使用scalac -Xprint:typer
编译此代码。您会看到同一隐式Predef.int2Integer
用于ev1
和ev2
参数。
旁注:最好避免asInstanceOf
强制转换,因为这些会破坏Scala类型系统的健全性。