【发布时间】:2018-10-26 12:35:44
【问题描述】:
我有一个第三方 Java API,其方法如下(简化):
public <C extends Comparable<C>> C jFoo(C c);
我想写一个这样的包装器:
def foo[C <: Comparable[C]](c: C): C = jFoo(c)
为了允许包装方法接受原语(因为据我了解,装箱无论如何都会发生,所以这无关紧要),我想专门化C:
def foo[@specialized(Int, Double) C <: Comparable[C]](c: C): C = jFoo(c)
但是,scalac 抱怨说,由于参数的上限,该方法不能被特化。
一种解决方案是添加一个证据参数:
def foo[@specialized(Int, Double) C, CC <: Comparable[CC]](c: C)
(implicit evComp: C => CC): CC =
jFoo(evComp(c))
这有效,您现在可以调用:
foo(2.0)
但是,方法签名(API 的一部分)现在并不真正可读。
在方法级别是否有替代方法可以产生等效、更易读的签名,同时保持专业化?
(Scala 2.12.x 很好,Dotty 没那么多)
【问题讨论】:
-
@YuvalItzchakov :问题是
Comparable不是作为类型类设计的——它是为存储状态而设计的,你不能在任何给定的C上使用它。另外,请注意您需要C <: Comparable[C],notComparable[C](不幸的是,这不是等效的)。 -
是的,它实际上也不匹配类型约束。
-
倒数第二个代码 sn-p 中的
evComp实际上是什么? -
@AndreyTyukin:抱歉,错字,已更正。这个隐式由 Scala 的 stdlib BTW 提供,至少对于 Doubles 来说是这样(但我假设其他原语也是如此)。
-
最后的代码 sn -p
foo(2.0)真的可以编译吗?我出于某种原因得到error: type arguments [Double,Any] do not conform to method foo's type parameter bounds [C,CC <: Comparable[CC]]。看起来好像它无法推断java.lang.Double作为第二个参数。
标签: scala comparable