Scala 2.10: why is there a type mismatch?

Can't figure out what is wrong with this code:

  trait NumberLike
  {
    def plus[T](a: T, b: T): T
  }

  class IntegerNumberLike extends NumberLike
  {
    def plus[Int](a: Int, b: Int): Int = 2 // type mismatch; found : scala.Int(2) required: Int
  }

      

But if I do that, it works:

  trait NumberLike[T]
  {
    def plus(a: T, b: T): T
  }

  class IntegerNumberLike extends NumberLike[Int]
  {
    def plus(a: Int, b: Int): Int = 2
  }

      

I had two questions:

  • Why is the first code example not working?
  • Generally, when should I use a class type parameter and when should I use a method type parameter?
+3


source to share


2 answers


Type parameters in methods are a lot like other parameters, the actual parameter name doesn't matter: plus[Int](a: Int, b: Int): Int

exactly the same asplus[T](a: T, b: T): T

Now it's easy to see why it plus[T](a: T, b: T): T = 2

won't compile, isn't it? Because 2

it is not of type T

.

As for your second question, it is difficult to answer precisely because it is quite broad. In short, parameterized classes and methods define a class or method template, respectively. Think of it as a family of classes / methods, not a single object. For example, plus[T] (a: T, b: T): T

one could write instead :

def plus(a: Int, b: Int): Int
def plus(a: Long, b: Long): Long
def plus(a: Double, b: Double): Double

      

and etc.



Or instead, class NumberLike[T]

you could:

class IntLike
class LongLike
class DoubleLike

      

and etc.



Looking at it this way, you might be asking yourself what exactly are you developing: is it a family of classes or a family of methods? When answering this question, you will say if you should parameterize a class, a method, or perhaps both ... Consider:

class Iterable[+A] {
    ...
    def def reduceLeft[B >: A](op: (B, A) ⇒ B): B
    ...
}

      

+2


source


Definition:

def plus[Int](a: Int, b: Int): Int

      

equivalent to

def plus[T](a: T, b: T): T

      



For example, you could see this more clearly in the following example:

  type Int = String

  def main(args: Array[String]) {
    val x: Int = "foo"
    println(x)
  }

      

where you get no error and "foo" is printed. Since you are only renaming your parametric type as Int (instead of T). So the compiler complains that Int (in this case the value is 2) and Int (your parametric type name) are not the same. I don't know if it is possible to implement a plus function for certain types from a parametric definition. You use class type parameters if the parameters are applicable to all classes and parameters of a method, if the parameters are applicable only to that method. It's just a matter of method visibility and responsibility.

+1


source







All Articles