文章目录
和java很类似,scala也有自己的可见性规则,不同的是scala只有private和protected关键字,没有public关键字,同时scala还提供了更加细粒度的访问控制如protected[scope]和private[scope]。
public
scala中默认的访问权限就是public,这意味着在scala中没有可见性关键字的声明体,他的访问权限就是public,是具有公有可见性的。这与Java不同,Java 语言中默认的“公有”可见性只对包可见(即包内私有)。
我们看一个例子:
package scopeA { class PublicClass1 { val publicField = 1 class Nested { val nestedField = 1 } val nested = new Nested } class PublicClass2 extends PublicClass1 { val field2 = publicField + 1 val nField2 = new Nested().nestedField } } package scopeB { class PublicClass1B extends scopeA.PublicClass1 class UsingClass(val publicClass: scopeA.PublicClass1) { def method = "UsingClass:" + " field: " + publicClass.publicField + " nested field: " + publicClass.nested.nestedField } }
我们可以看到PublicClass1和它的内部类Nested的字段是公有可以访问的。
Protected
所有使用protected 关键字声明的成员只对该定义类型可见,包括
相同类型的其他实例以及所有的继承类型。
我们看一个例子:
package scopeA { class ProtectedClass1(protected val protectedField1: Int) { protected val protectedField2 = 1 def equalFields(other: ProtectedClass1) = (protectedField1 == other.protectedField1) && (protectedField2 == other.protectedField2) && (nested == other.nested) class Nested { protected val nestedField = 1 } protected val nested = new Nested } class ProtectedClass2 extends ProtectedClass1(1) { val field1 = protectedField1 val field2 = protectedField2 val nField = new Nested().nestedField // ERROR } class ProtectedClass3 { val protectedClass1 = new ProtectedClass1(1) val protectedField1 = protectedClass1.protectedField1 // ERROR val protectedField2 = protectedClass1.protectedField2 // ERROR val protectedNField = protectedClass1.nested.nestedField // ERROR } protected class ProtectedClass4 class ProtectedClass5 extends ProtectedClass4 protected class ProtectedClass6 extends ProtectedClass4 } package scopeB { class ProtectedClass4B extends scopeA.ProtectedClass4 // ERROR }
由于ProtectedClass2 继承了Protected1 类,因此ProtectedClass2 能访问
ProtectedClass1中定义的受保护成员。不过,ProtectedClass2 无法访问protectedClass1.nested 对象中受保护的nestedField 成员。
同时,ProtectedClass3 类也无法访问它使用的ProtectedClass1实例中的受保护成员。
最后,由于ProtectedClass4 被声明为protected 类,其对scopeB 包内的对象不可见。
private
私有(private)可见性将实现细节完全隐藏起来,即便是继承类的实现者也无法访问这些细节。声明中包含了private 关键字的所有成员都只对定义该成员的类型可见,该类型的其他实例也能访问这些成员。
注意,虽然private的继承者无法访问成员,但是包含该字段的类型的其他实例也可以访问这些成员。
举个例子:
package scopeA { class PrivateClass1(private val privateField1: Int) { private val privateField2 = 1 def equalFields(other: PrivateClass1) = (privateField1 == other.privateField1) && (privateField2 == other.privateField2) && (nested == other.nested) class Nested { private val nestedField = 1 } private 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 } private class PrivateClass4 class PrivateClass5 extends PrivateClass4 // ERROR protected class PrivateClass6 extends PrivateClass4 // ERROR private class PrivateClass7 extends PrivateClass4 } package scopeB { class PrivateClass4B extends scopeA.PrivateClass4 // ERROR }
其他的都很好解释, 请注意,equalFields 方法可以访问其他实例中定义的私有成员。