我想知道为什么下面的示例允许使用两个具有相同名称(“A”)的类型参数(名为“A”)。我知道这是类型参数的命名错误,请不要这样做。

(我的猜测是它们处于不同的作用域级别,例如类级别和函数级别,并且编译器正在使用某种名称处理)

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 
   } 
} 

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 

请您参考如下方法:

Scala中的嵌套作用域可以自由隐藏彼此的符号表。类型不是唯一可以做到这一点的事情。例如:

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." 
      } 
    } 
  } 
} 

原理是范围可以控制其 namespace 。这很危险,如果您愚蠢地使用它(例如,我为三种不同的事物分别使用了 Xa,而为两种使用了 A-实际上,您可以用 X替换每个标识符,但 Some中的标识符除外)小写)。但这在编写功能代码时也有好处-您不必担心仅仅因为您碰巧将其放在不同的上下文中而需要重命名一些迭代变量或类型之类的东西。
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 
} 

因此请注意,您有权迷惑自己,并明智地选择不混淆地使用该能力。


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!