Two types with the same name

I am wondering why two type parameters (named "A") with the same name ("A") are allowed according to the example below. I know this is a POOR type parameter assignment, do not do this.

(I assume that they are at a different level of visibility, for example, at the class level and function level, and the compiler uses some kind of name)

class MyTest[A](){ type MyType = A def checkString[A](value:A, x:MyType):A = { value match { case x:String => println("Value is a String") case _ => println("Value is not a String") } x match { case x:String => println("x is a String") case _ => println("x is not a String") } value } } 

Example output from 2.8.0

 scala> val test = new MyTest[Int] test: MyTest[Int] = MyTest@308ff65f scala> test.checkString("String",1) Value is a String x is not a String res7: java.lang.String = String scala> test.checkString(1,1) Value is not a String x is not a String res8: Int = 1 
+6
generics scala
source share
4 answers

Nested areas in Scala can obscure each other's character tables. Types are not the only things you can handle. For example:

 class X[A](a: A) { def X[A](a: A) { if (a==this.a) { val X = Some(this.a) X match { case Some(a) => "Confused much yet?" case _ => "Just because you can do this doesn't mean you should." } } } } 

The principle is that scope controls the namespace. This is dangerous if you use it stupidly (for example, I used X and a for each of three different things, and a for two - in fact, you could replace each identifier with X , except for one in Some , which should be lower register). But it also has advantages when writing functional code β€” you don’t have to worry about renaming any variable or type of iteration, or anything else, just because you put it in a different context.

 def example = { val a = Array(1,2,3,4,5) val sumsq = a.map(i => i*i).sum a.map(i => { val a = Array.range(1,i) val sumsq = a.map(i => i*i).sum // Cut and paste from above, and works! sumsq + i }).sum } 

So keep in mind that you have the ability to confuse and use this power wisely without getting confused.

+8
source share

I am not a Scala expert, but your code behaves exactly as I expected.

First, you need to know that a method type parameter is not necessarily associated with a class.

For example, the following Scala is valid.

 class Test1 { def test[A] (x: A) = println(x) } 

And the following is also valid Scala code, the only difference is that it does not use type A at all.

 class Test2[A] { def test (x: Int) = println(x) } 

So, I think it’s clear now, first you created an instance of MyTest [Int], and that’s fine.

 scala> val test = new MyTest[Int] test: MyTest[Int] = MyTest@308ff65f 

Then you call checkString [A, Int] without specifying type A, since this is a general function, the compiler should infer which type is A.

 scala> test.checkString("String",1) Value is a String x is not a String res7: java.lang.String = String 

Note:

At this point in time, Scala already knows that x must be an Int and its type is fixed, since you provide it with MyTest [Int]. Thus, the following code will give a compilation error.

 scala> val t = new MyTest[Int] t: MyTest[Int] = MyTest@cb800f scala> t.checkString ("A", "B") <console>:8: error: type mismatch; found : java.lang.String("B") required: t.MyType t.checkString ("A", "B") 

Now the compiler is looking at the arguments that you provided, and found that it is

 checkString ("String", 1) 

which corresponds

 checkString (value: A, x: Int) 

So, now the compiler knows type A in checkString [A, Int] should be a string, and if you do all this manually, 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) <console>:8: error: type mismatch; found : java.lang.String("String") required: Int test.checkString[Int] ("String", 4) ^ 
+4
source share

Well, I believe in scala, we use the same rule as in Java, basically we are looking for the smallest available area in Java:

 class Foo<T>{ T instance; void <T> T getInstance(){ return instance } } 

Throws a compilation error, since the type T declared in the universal getInstance method does not match the parameter type of the Foo class. In the case of scala, I believe that you write

 def checkString[A] 

You tell the compiler that the behavior of the function depends on the type, but has nothing to do with the class of parameters of the outer class. Unfortunately, right now I cannot find the correct scala spec location.

+1
source share

Its not only associated with scala. In most languages ​​you can do this. Because, as you said, variables are in different areas.

In c #

 class test { int i; void method(int i) { this.i = i; } } 

it is a type of self. I am not sure about this function in scala. But the reason for your question is the level of coverage.

0
source share

All Articles