Vadim Samokhin
Vadim Samokhin

Reputation: 3456

scala 2.10: why there is a type mismatch?

Can't figure out what's 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 it this way, 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
  }

So I got two questions:

Upvotes: 3

Views: 135

Answers (2)

Dima
Dima

Reputation: 40510

Type parameters in methods are much like other parameters, the name of actual parameter isn't significant: plus[Int](a: Int, b: Int): Int is exactly the same as plus[T](a: T, b: T): T

Now, it is easy to understand why plus[T](a: T, b: T): T = 2 does not compile, isn't it? Because 2 is not of type T.

As to your second question, it is hard to answer exactly, because it is rather broad. In a nutshell, parametrized classes and methods define a template of a class or a method respectively. Think of it as a family of classes/methods rather than a single object. For example, instead of plus[T] (a: T, b: T): T, one could have written:

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

etc.

Or, instead of class NumberLike[T], you could have:

class IntLike
class LongLike
class DoubleLike

etc.

Looking at it this way, you can ask yourself a question, what it is you are designing: is it a family of classes or a family of methods? Answering that question will tell you whether you should parametrize a class, a method, or, perhaps, both ... Consider:

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

Upvotes: 2

ale64bit
ale64bit

Reputation: 6242

The definition:

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

is equivalent to

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

For example, you could see it more clearly through the following example:

  type Int = String

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

where you get no errors and "foo" printed. Since you are only renaming your parametric type as Int (instead of T). That's why the compiler complains that Int (in this case the value of 2) and Int (your parametric type name) are not the same. I don't know if you can implement the plus function for specific types out of the parametric definition. You use class type parameters if the parameters apply to all the class, and method parameters if the parameters apply only to that method. It's just a matter of visibility and responsibility of the methods.

Upvotes: 1

Related Questions