I am wondering why the two type parameters (named \"A\") with the same name (\"A\") is allowed as per the example below. I know this is a POOR naming of type parameters, do
I'm not expert of Scala, but your code behave exactly what I would expected.
First, you need to know that the type parameter of method is not need bound to class.
For example, the following is valid Scala.
class Test1 {
def test[A] (x: A) = println(x)
}
And the following is also a valid Scala code, the only different is that this one does not use the type A at all.
class Test2[A] {
def test (x: Int) = println(x)
}
So I think it is clear now, first you created a instance of MyTest[Int], which is fine.
scala> val test = new MyTest[Int]
test: MyTest[Int] = MyTest@308ff65f
Then you called checkString[A, Int] without provide type parameter A, since it is a generic function, the compiler must inference what type is A.
scala> test.checkString("String",1)
Value is a String
x is not a String
res7: java.lang.String = String
Note:
In this time point, Scala already knows that x must be a Int and its type is fixed, since you provide it by MyTest[Int]. So the following code will yield compile error.
scala> val t = new MyTest[Int]
t: MyTest[Int] = MyTest@cb800f
scala> t.checkString ("A", "B")
:8: error: type mismatch;
found : java.lang.String("B")
required: t.MyType
t.checkString ("A", "B")
Now the complier looks at the arguments you provided, and found its is
checkString ("String", 1)
which is corresponding to
checkString (value: A, x: Int)
So now compiler knows type A in checkString[A, Int] must be a string, and if you do all of this by hand, your code will look like this.
scala> val test = new MyTest[Int]
test: MyTest[Int] = MyTest@5bda13
scala> test.checkString[String]("String", 1)
Value is a String
x is not a String
res1: String = String
scala> test.checkString[Int] (3, 4)
Value is not a String
x is not a String
res4: Int = 3
scala> test.checkString[Int] ("String", 4)
:8: error: type mismatch;
found : java.lang.String("String")
required: Int
test.checkString[Int] ("String", 4)
^