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 i
You can also use a type bound on the type parameter, which is enforced by an implicit argument:
trait Col[T] extends Traversable[T] {
def sum(implicit ev: T <:< Int) :T = (0/:this)(_+_)
}
<:<
is actually a class, expressed in infix notation, defined in Predef.scala and explained in many places, including here
<:<
means 'must be a subtype of'
You can also use =:=
'must be equal to' and X <%< Y
'must be viewable as' (ie. there is an implicit conversion to X from Y)
For a more detailed explanation of type constraints, see this SO question.
there is another option involving implicit classes conversions
trait Col[T] extends Traversable[T]
implicit class ColInt[T <: Int](val v : Col[T]) extends AnyVal {
def sum : T = (0 /: v)(_ + _)
}
in this context you don't need the empty trait Col anymore, so you could further comprimize it to this:
implicit class ColInt[T <: Int](val v : Traversable[T]) extends AnyVal {
def sum : T = (0 /: v)(_ + _)
}
The advantage of this method is, that it tells the compiler, that type T is really a subtype of Int, so List[T] <: List[Int]
is still valid in this context, and no explicit conversion needs to be added. The implicit parameter adds implicit conversions that wouldn't work on List[T]
, because it only introduces an implicit conversion from T
to Int
, not from List[T]
to List[Int]
In this case you can only use an implicit parameter, as the type gets determined before the method call.
trait Col[T] extends Traversable[T] {
def sum(implicit num: Numeric[T]) :T = ???
}
If the method you are calling would be parameterized, you could use context bounds, which are just syntactic sugar for the implicit parameter bound to the type parameter:
def foo[A](implicit ev: Something[A]) = ???
is equivalent to
def foo[A : Something] = ???