第二十六章 访问控制
3. Access Control Syntax (访问控制语法)
在实体的介绍符之前我们可以用这五个修饰符(open
,public
,internal
,fileprivate
或private
)来定义实体的五种访问级别。
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}
除非专门指定,否则实体默认的访问级别为内部访问级别,详见默认访问级别。这意味着在不使用修饰符显式声明访问级别的情况下,SomeInternalClass
和someInternalConstant
仍然拥有隐式的内部访问级别:
class SomeInternalClass {} // implicitly internal
let someInternalConstant = 0 // implicitly internal
4. Custom Type (自定义类型)
如果我们想为一个自定义类型指明某个访问级别,在定义该类型的时候顺便就可以指明其的访问级别,这时新的类型就可以使用在它的访问级别允许的任何地方。举个例子,如果我们定义了一个文件私有的类,那这个类就只能在定义它的源文件中使用,可以作为属性类型、函数参数类型或者返回类型,等等。
类型的访问控制级别同样也会影响类型成员(属性,方法,构造器和下标)的默认访问级别。如果将类型的访问级别定义为私有或文件私有,那么该类型的成员访问级别也将会被定义为私有或文件私有。如果我们将一个类型的访问级别定义为内部或公共(或使用了一个默认的内部访问级别并没有明确的指明访问级别),该类型成员的访问级别也将会是内部的。
public class SomePublicClass { // 明确的访问级别
public var somePublicProperty = 0 // 明确的访问级别
var someInternalProperty = 0 // 隐含的访问级别
fileprivate func someFilePrivateMethod() {} // 明确的访问级别
private func somePrivateMethod() {} // 明确的访问级别
}
class SomeInternalClass { // 隐含的访问级别
var someInternalProperty = 0 // 隐含的访问级别
fileprivate func someFilePrivateMethod() {} // 明确的访问级别
private func somePrivateMethod() {} // 明确的访问级别
}
fileprivate class SomeFilePrivateClass { // 明确的访问级别
func someFilePrivateMethod() {} // 隐含的访问级别
private func somePrivateMethod() {} // 明确的访问级别
}
private class SomePrivateClass { // 明确的访问级别
func somePrivateMethod() {} // 隐含的访问级别
}
4.1 Tuple Types (元组类型)
元组类型的访问级别是该元组中使用的所有类型中限制最多的访问级别,举个例子,如果我们将两个不同的类型组合为一个元组,一个是内部访问,一个是私有访问,那么该元组的访问级别将会是私有的。访问的级别也哟一定的顺序。
4.2 Function Types (函数类型)
函数类型的访问级别被函数的参数类型和返回类型计算为限制最多的访问级别,但是,如果这种访问级别不符合函数定义所在环境的默认访问级别,那么就需要明确地指定该函数的访问级别。
下面的这个例子定义了一个全局函数someFunction()
,并没有为次函数提供一个特定的访问级别修饰符,我们希望该函数有一个默认的内部访问级别,但是该例并不是这种情况,事实上,someFunction()代码的写法并不能编译成功。
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
}
该函数的返回类型是由两个自定义的类组成的一个元组,一个类是内部访问,另一个类是私有访问,因此该返回类型的整体访问级别是私有的,(私有访问级别是元组组成类型的最小访问级别)
因为函数的返回类型是私有的,为了是 函数的定义有效。我们要将函数的整个访问级别用private
修饰符标记,
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
}
使用public或internal修饰符来标记该函数someFunction()的定义,或者使用默认的内部访问级别都是无效的,因为如果把函数的访问级别看作公共的或者是内部访问来使用,那么我们可能将无法读取使用在函数返回类型中私有的类,It’s not valid to mark the definition of someFunction() with the public or internal modifiers, or to use the default setting of internal, because public or internal users of the function might not have appropriate access to the private class used in the function’s return type.
4.3 Enumeration Types (枚举类型)
每一个枚举成员都会自动接受他们的枚举所使用的访问级别。我们不可以对每一个枚举成员指定不同的访问级别。下面的这个例子,枚举CompassPoint
它有一个明确的访问级别public
,因此该枚举的成员会自动接受枚举所使用的访问级别。
public enum CompassPoint {
case north
case south
case east
case west
}
4.4 Raw Values and Associated Values (原始值和关联值)
类型使用了枚举成员原始值或关联值的访问级别必须要和枚举的访问级别一样高。举个例子,比如说我们不能使用private访问级别来对定义原枚举成员的原始值的internal访问级别的类型。原枚举成员的原始值是internal访问级别,
4.5 Nested Types (嵌套类型)
嵌套类型的访问级别和由它所包含的类访问级别是一致的。定义在public类型中的嵌套类型会自动接受internal访问级别的。如果说我们想要在public访问级别里面的嵌套类型的访问级别是public,那么我们就要在定义嵌套类型的时候将它定义为public访问级别即可。