具有类型参数限制的Scala泛型类的条件方法

时间:2013-07-22 18:34:31

标签: scala generics

我相信泛型类可以使其方法之一只能假设其类型参数符合一些额外限制,例如(现场即兴语法):

trait Col[T] extends Traversable[T] {
    def sum[T<:Int] :T = (0/:this)(_+_)
}

我想我可以使用隐式参数作为证据......是否有语言功能?

3 个答案:

答案 0 :(得分:7)

您还可以在type参数上使用类型绑定,该参数由隐式参数强制执行:

trait Col[T] extends Traversable[T] {
    def sum(implicit ev: T <:< Int) :T = (0/:this)(_+_)
}

<:<实际上是一个以中缀表示法表示的类,在Predef.scala中定义并在许多地方进行了解释,包括here

<:<表示'必须是'

的子类型

您还可以使用=:='必须等于'且X <%< Y'必须可以查看为'(即,从Y隐式转换为X)

有关类型约束的更详细说明,请参阅this SO question

答案 1 :(得分:3)

在这种情况下,您只能使用隐式参数,因为在方法调用之前确定了类型。

trait Col[T] extends Traversable[T] {
  def sum(implicit num: Numeric[T]) :T = ???
}

如果要调用的方法是参数化的,则可以使用上下文边界,这只是绑定到type参数的隐式参数的语法糖:

def foo[A](implicit ev: Something[A]) = ???

相当于

def foo[A : Something] = ???

答案 2 :(得分:1)

还有另一个涉及隐式类转换的选项

trait Col[T] extends Traversable[T] 

implicit class ColInt[T <: Int](val v : Col[T]) extends AnyVal {
    def sum : T = (0 /: v)(_ + _)
}

在这种情况下,你不再需要空特性Col,所以你可以进一步将其简化为:

implicit class ColInt[T <: Int](val v : Traversable[T]) extends AnyVal {
    def sum : T = (0 /: v)(_ + _)
}

这个方法的优点在于,它告诉编译器,类型T实际上是Int的子类型,因此List[T] <: List[Int]在此上下文中仍然有效,并且不需要添加显式转换。隐式参数添加了对List[T]不起作用的隐式转换,因为它只引入了从TInt的隐式转换,而不是List[T]到{{{ 1}}