在scala中,我们可以使用隐式类型来有条件地将方法添加到依赖于该类型参数的参数化类型上。例如,Iterator.sum
:
def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
甚至可以调用此方法的Numeric
类型类的实例:
scala> List(1, 2, 3).sum
res0: Int = 6
scala> List("a", "b").sum
<console>:6: error: could not find implicit value for parameter num: Numeric[java.lang.String]
List("a", "b").sum
^
到目前为止,这么好。假设我想要一些集合类型My2Col
:
class My2Col[A](a1 : A, a2 : A)
但我想强制要求,如果这是A : Numeric
,然后 a2 > a1
。但是,完全有效是因为A
不是数字。
My2Col("a", "b") //OK
My2Col("b", "a") //OK
My2Col(1, 2) //OK
My2Col(2, 1) //THROW IllegalArgumentException
有没有人想过如何做到这一点?
PS。如果有人对更好的问题标题有任何建议,我都是耳朵
答案 0 :(得分:12)
class My2Col[A](a1 : A, a2 : A)(implicit num: Numeric[A] = null){
for{check <- Option(num); if(check.gteq(a1, a2))}
throw new IllegalArgumentException
}
答案 1 :(得分:3)
我会通过创建表示需求的2个含义来实现这一点,一个更通用(除了Int
或Numeric[T]
以外的所有类型),另一个更具体(对于{ {1}}或Int
)。
然后,按照隐式解析的规则,我会将更具体的一个放在Numeric[T]
类型的伴随对象中,而将更一般的放在伴随对象的基类中。这样我就可以确保编译器首先尝试应用更具体的一个。
当然,缺点是如果用户明确提供隐式参数,则可以规避此机制不进行检查。
这样的事情(其中Requirement
是具有特定规则的类型,Int
是集合类):
Foo