8

I believe that a generic class may make one of its methods available only assuming that its type parameters conform to some additional restrictions, something like (syntax improvised on the spot):

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

I guess I could use implicit parameters as evidence... Is there a language feature for this?

4

3 回答 3

8

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

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

<:<实际上是一个类,用中缀表示法表示,在Predef.scala中定义并在很多地方解释过,包括这里

<:<表示“必须是”的子类型

您还可以使用=:=“必须等于”和X <%< Y“必须可查看为”(即存在从 Y 到 X 的隐式转换)

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

于 2013-08-27T12:24:43.007 回答
4

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

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

如果您正在调用的方法将被参数化,您可以使用上下文边界,这只是绑定到类型参数的隐式参数的语法糖:

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

相当于

def foo[A : Something] = ???
于 2013-07-22T18:44:32.423 回答
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],因为它只引入了隐式转换 from Tto Int,而不是 from List[T]toList[Int]

于 2016-05-31T16:36:35.887 回答