Question

As far as I know, there are two ways to add type constraint.

trait Dummy

First way

def doStuff[T <: Dummy](x: T) = x

Second way

def doStuff[T](x: T)(implicit x: T <:< Dummy) = x

Both achieve the same result.

I just wonder that what kind of scenarios I should use the upper bound or lower bound directly, or I should use implicit to append the constraint on the type.

Was it helpful?

Solution

One necessitates the creation of an implicit object on each invocation of the call, the other merely places a type constraint on the object passed into the function. In general, I would prefer the declaration wherein you state [T <: Dummy] rather than the implicit.

Where you'd use the implicit is when you want to create a type which can do certain things but only if it satisfies a certain constraint. Hence, you see the following in List[A] declaration:

 def sum(implicit ev: Numeric[A]) = ...

which is a nice way of saying "you can place any type 'A' in the class but if you want to use 'sum' it has to conform to..." Take for instance the following class definition:

 class Foo[T](value: T){
   def doubleString = value.toString() + value.toString()

   def specialSauce(implicit ev: T <:< Dummy): Dummy = ...
 }

This allows me the option to create some type of Foo[Int] and it will work but won't allow me to call the specialSauce method of the class unless T is a direct descendent of Dummy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top