scala教程之:可见性规则(二)

简介: scala教程之:可见性规则(二)

scoped private 和 scoped protected


除了普通的public,private和protected这三种可见性外,scala还提供了范围内的可见性: scoped private 和 scoped protected。 scala的范围有this,package和具体的某个类型。


简单点讲范围内的可见性就是在范围内保持该可见性的特性。


我们可以比较一下上面我们在讲private和proteced可见性的时候,两者在范围内(class,package)的表现是一样的,是可以替换的,只有在继承方面有差异。

我们先看一下继承的差异性:


package scopeA {
  class Class1 {
    private[scopeA]   val scopeA_privateField = 1
    protected[scopeA] val scopeA_protectedField = 2
    private[Class1]   val class1_privateField = 3
    protected[Class1] val class1_protectedField = 4
    private[this]     val this_privateField = 5
    protected[this]   val this_protectedField = 6
  }
  class Class2 extends Class1 {
    val field1 = scopeA_privateField    
    val field2 = scopeA_protectedField  
    val field3 = class1_privateField     // ERROR
    val field4 = class1_protectedField  
    val field5 = this_privateField       // ERROR
    val field6 = this_protectedField  
  }
}
package scopeB {
  class Class2B extends scopeA.Class1 {
    val field1 = scopeA_privateField     // ERROR
    val field2 = scopeA_protectedField  
    val field3 = class1_privateField     // ERROR
    val field4 = class1_protectedField  
    val field5 = this_privateField       // ERROR
    val field6 = this_protectedField  
  }
}


scope private/protected只能在该scope内部满足private/protected条件时候才能访问,这样就提供了更加细粒度的控制。


其中this scope是最严格的可见性,它表明可见性限制的字段只能在当前的scope或者type范围之内。


package scopeA {
class PrivateClass1(private[this] val privateField1: Int) {
private[this] val privateField2 = 1
def equalFields(other: PrivateClass1) =
(privateField1 == other.privateField1) && // 错误
(privateField2 == other.privateField2) && // 错误
(nested == other.nested) // 错误
class Nested {
private[this] val nestedField = 1
}
private[this] val nested = new Nested
}
class PrivateClass2 extends PrivateClass1(1) {
val field1 = privateField1 // 错误
val field2 = privateField2 // 错误
val nField = new Nested().nestedField // 错误
}
class PrivateClass3 {
val privateClass1 = new PrivateClass1(1)
val privateField1 = privateClass1.privateField1 // 错误
val privateField2 = privateClass1.privateField2 // 错误
val privateNField = privateClass1.nested.nestedField // 错误
}
}


我们先看一下类型范围的private[this], 因为其是特定类型范围内,所以equalFields方法会编译错误,其无法被其他实例所访问。


除此之外,使用private[this] 修饰的类成员的可见性与未指定作用域范围的private 可见性一致。


再看一下包范围内的private[this] :


package scopeA {
private[this] class PrivateClass1
package scopeA2 {
private[this] class PrivateClass2
}
class PrivateClass3 extends PrivateClass1 // 错误
protected class PrivateClass4 extends PrivateClass1 // 错误
private class PrivateClass5 extends PrivateClass1
private[this] class PrivateClass6 extends PrivateClass1
private[this] class PrivateClass7 extends scopeA2.PrivateClass2 // 错误
}
package scopeB {
class PrivateClass1B extends scopeA.PrivateClass1 // 错误
}


在相同包中,无法成功地为一个private[this] 类型声明public 或protected 子类,你只能为其声明private 和private[this] 子类。


与此同时,由于PrivateClass2 的可见性被限定在scopeA2 作用域内,因此你无法在scopeA2 作用域外声明其子类。


同理,在与scopeA2无关的scopeB 作用域内使用PrivateClass1 声明类同样会失败。


我们再看下private[T] 的可见性,其中T 代表了某一类型


package scopeA {
  class PrivateClass1(private[PrivateClass1] val privateField1: Int) {
    private[PrivateClass1] val privateField2 = 1
    def equalFields(other: PrivateClass1) =
      (privateField1 == other.privateField1) &&
      (privateField2 == other.privateField2) &&
      (nested  == other.nested)
    class Nested {
      private[Nested] val nestedField = 1
    }
    private[PrivateClass1] val nested = new Nested
    val nestedNested = nested.nestedField   // ERROR
  }
  class PrivateClass2 extends PrivateClass1(1) {
    val field1 = privateField1  // ERROR
    val field2 = privateField2  // ERROR
    val nField = new Nested().nestedField  // ERROR
  }
  class PrivateClass3 {
    val privateClass1 = new PrivateClass1(1)
    val privateField1 = privateClass1.privateField1  // ERROR
    val privateField2 = privateClass1.privateField2  // ERROR
    val privateNField = privateClass1.nested.nestedField // ERROR
  }
}


由于可见性类型为private[PrivateClass1] 的成员对其他同类型实例可见, 因此

equalFields 能够通过解析。


我们再看看包级的可见性:


package scopeA {
  private[scopeA] class PrivateClass1
  package scopeA2 {
    private [scopeA2] class PrivateClass2
    private [scopeA]  class PrivateClass3
  }
  class PrivateClass4 extends PrivateClass1
  protected class PrivateClass5 extends PrivateClass1
  private class PrivateClass6 extends PrivateClass1
  private[this] class PrivateClass7 extends PrivateClass1
  private[this] class PrivateClass8 extends scopeA2.PrivateClass2 // ERROR
  private[this] class PrivateClass9 extends scopeA2.PrivateClass3
}
package scopeB {
  class PrivateClass1B extends scopeA.PrivateClass1 // ERROR
}


现在我们无法在scopeA2 作用域外将PrivateClass2 子类化。不过由于PrivateClass3 被声明为private[ScopeA] 类型,因此我们可以在scopeA 作用域内能将PrivateClass3 子类化。


再看看放在类型里面的包级可见性:


package scopeA {
  class PrivateClass1(private[this] val privateField1: Int) {
    private[this] val privateField2 = 1
    def equalFields(other: PrivateClass1) =
      (privateField1 == other.privateField1) && // ERROR
      (privateField2 == other.privateField2) && // ERROR
      (nested == other.nested)   // ERROR
    class Nested {
      private[this] val nestedField = 1
    }
    private[this] val nested = new Nested
  }
  class PrivateClass2 extends PrivateClass1(1) {
    val field1 = privateField1  // ERROR
    val field2 = privateField2  // ERROR
    val nField = new Nested().nestedField  // ERROR
  }
  class PrivateClass3 {
    val privateClass1 = new PrivateClass1(1)
    val privateField1 = privateClass1.privateField1  // ERROR
    val privateField2 = privateClass1.privateField2  // ERROR
    val privateNField = privateClass1.nested.nestedField // ERROR
  }
}


如果我们试图从某个与scopeA 无关的包scopeB 中访问scopeA 时,或者当我们尝试从嵌套包scopeA2 中访问成员变量时,便会出现错误。


相关文章
|
分布式计算 Java Scala
一天学完spark的Scala基础语法教程十三、文件IO操作(idea版本)
一天学完spark的Scala基础语法教程十三、文件IO操作(idea版本)
111 0
一天学完spark的Scala基础语法教程十三、文件IO操作(idea版本)
|
分布式计算 Java Scala
一天学完spark的Scala基础语法教程十二、异常处理(idea版本)
一天学完spark的Scala基础语法教程十二、异常处理(idea版本)
192 0
一天学完spark的Scala基础语法教程十二、异常处理(idea版本)
|
分布式计算 Java Scala
一天学完spark的Scala基础语法教程十一、正则表达式(idea版本)
一天学完spark的Scala基础语法教程十一、正则表达式(idea版本)
147 0
一天学完spark的Scala基础语法教程十一、正则表达式(idea版本)
|
存储 分布式计算 Java
一天学完spark的Scala基础语法教程十、类和对象(idea版本)
一天学完spark的Scala基础语法教程十、类和对象(idea版本)
119 0
一天学完spark的Scala基础语法教程十、类和对象(idea版本)
|
分布式计算 Scala Spark
一天学完spark的Scala基础语法教程九、迭代器(idea版本)
一天学完spark的Scala基础语法教程九、迭代器(idea版本)
125 0
一天学完spark的Scala基础语法教程九、迭代器(idea版本)
|
分布式计算 Scala Spark
一天学完spark的Scala基础语法教程八、集合(idea版本)
一天学完spark的Scala基础语法教程八、集合(idea版本)
139 0
一天学完spark的Scala基础语法教程八、集合(idea版本)
|
存储 分布式计算 Scala
一天学完spark的Scala基础语法教程七、数组(idea版本)
一天学完spark的Scala基础语法教程七、数组(idea版本)
127 0
一天学完spark的Scala基础语法教程七、数组(idea版本)
|
分布式计算 Scala Spark
一天学完spark的Scala基础语法教程六、字符串(idea版本)-2
一天学完spark的Scala基础语法教程六、字符串(idea版本)
127 0
一天学完spark的Scala基础语法教程六、字符串(idea版本)-2
|
分布式计算 Java Scala
一天学完spark的Scala基础语法教程六、字符串(idea版本)-1
一天学完spark的Scala基础语法教程六、字符串(idea版本)
112 0
一天学完spark的Scala基础语法教程六、字符串(idea版本)-1
|
分布式计算 Scala Spark
一天学完spark的Scala基础语法教程五、闭包(idea版本)
一天学完spark的Scala基础语法教程五、闭包(idea版本)
82 0
一天学完spark的Scala基础语法教程五、闭包(idea版本)