使用隐式方法
最常见和通用的方法是使用 Predef 中定义的implicitly method:
def add[T: Numeric](x: T, y: T) = implicitly[Numeric[T]].plus(x,y)
显然,这有点冗长,需要重复类型类的名称。
引用证据参数(不要!)
另一种选择是使用编译器自动生成的隐式证据参数的名称:
def add[T: Numeric](x: T, y: T) = evidence$1.plus(x,y)
令人惊讶的是,这种技术甚至是合法的,并且在实践中不应该依赖它,因为证据参数的名称可能会改变。
更高种类的上下文(引入context 方法)
相反,可以使用implicitly 方法的增强版本。请注意,隐式方法定义为
def implicitly[T](implicit e: T): T = e
这个方法只是依赖编译器从周围的作用域中插入一个正确类型的隐式对象到方法调用中,然后返回它。我们可以做得更好:
def context[C[_], T](implicit e: C[T]) = e
这允许我们将add 方法定义为
def add[T: Numeric](x: T, y: T) = context.plus(x,y)
context方法类型参数Numeric和T是从作用域推断出来的!不幸的是,这种context 方法在某些情况下不起作用。例如,当一个类型参数具有多个上下文边界或有多个具有不同上下文边界的参数时。我们可以用稍微复杂一点的版本来解决后一个问题:
class Context[T] { def apply[C[_]]()(implicit e: C[T]) = e }
def context[T] = new Context[T]
这个版本要求我们每次都指定类型参数,但是处理多个类型参数。
def add[T: Numeric](x: T, y: T) = context[T]().plus(x,y)