我有第三方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没那么多)
答案 0 :(得分:2)
您可以通过使其成为特殊CC
类型类的类型成员来摆脱第二个类型参数EvC
。
以下作品:
import java.lang.Comparable
def jFoo[C <: Comparable[C]](c: C): Unit = println("compiles => ship it")
trait EvC[C] {
type CC <: Comparable[CC]
def apply(c: C): CC
}
def foo[@specialized(Int, Double) C](c: C)(implicit evC: EvC[C]): Unit =
jFoo[evC.CC](evC(c))
implicit object DoubleEvC extends EvC[Double] {
type CC = java.lang.Double
def apply(c: Double) = (c: java.lang.Double)
}
foo(42.0) // compiles => ship it
从某种意义上说,我只是将C => CC
部分与类型参数CC
本身粘在一起,以便CC
类型不再出现在类型参数中名单。我不确定你是否可以彻底摆脱所有这一切,但内置原语类型没有实现java.lang.Comparable
仍然是事实。