Swift4语法极简手册 — Access Control

Swift4语法极简手册

第二十四章节:Access Control

Access Control

Access Control是Swift4中的访问控制机制,它基于两个基本的理念

  1. Modules 模块
  2. Source Files 源文件

Module 模块

Swift中一个Module就是一个独立的部署单元,如frameworkapplication

当你引用任何framework时,framework就是一个Module, application中的每个taget也是一个Module

Source File 源文件

每个以.swift结尾的文件就是source file

在swift中,一个source file可以定义任何多个Type

Access Levels

Swift4的Acess Conrol分为以下几个级别

  1. Open Access 以及. Public Access

    开放权限

  2. Internal Acess

    允许Module内部访问

  3. File-Private Access

    文件访问权限,同一source file中可访问

  4. Private Access

    私有权限,同一Type内才允许访问

它们的开放级别从高到低,Open Acess最高,而Private Access最低

Open Acess 对比 Public Access

Open Access最能用于定义classess以及class memers,它与Public Acess的区分在于:

  • Classes如果以Public定义或更低权限,只能在同一Module中被继承;
  • Classes的members如果以Public或更低权限定义,只能在同一Module中被override
  • Classes以Open权限定义,可以在Module内及导入Module的范围内被子类化
  • Class member以Open权限定义,可以在Module内及导入Module的范围内被override

如果你写了一个framework,你的public类,别人不能继承,重写它的属性或方法;但你的Open类或Open member,别人可以继承并override

Access Levels准则

一个entity的权限不能定义的比它所处的entity低

如:

  • 一个public的method,它的parameters,return等的权限不能低于public
  • 一个Private Type的Property不能被定义为Public权限

默认Access Level

如果没有显式的定义,所有entity的权限有internal的默认权限

如果你只是编写一个Single - Target App,那你可以忽略Access Level, 所有的使用默认的internal权限就可以了

Access Control Syntax

1
2
3
4
5
6
7
8
9
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() {}

如上,使用关键字public,open,internal,fileprivate,private来定义Access Control,它可以定义在Type,Property,Method,Subscpript等前

不使用Access Control关键字,则为默认的internal权限

1
2
//Access Control为internal级别
class SomeInternalClass {}

Access Level规范指引

Types

对于Classes,Enumeration,Structure等,你可以给Type,Type中的properties,methods定义Access Level

1
2
3
4
5
6
public class SomePublicClass { // 类被定义为public
public var somePublicProperty = 0 // 属性被定义为public
var someInternalProperty = 0 // 未定义,默认为internal
fileprivate func someFilePrivateMethod() {} // 方法被定义为fileprivate
private func somePrivateMethod() {} // 方法定义为private
}

对于PublicOpen权限的Class,其properties, methods的默认权限为internal,而不是public

Tuple Types

对于Tuple Types来说,几个tuple中,权限最低的为此Tuple Type的权限

1
(SomeInternalClass, SomePrivateClass) //Access Level 为 Private

如上,Tuple中一个为Internal,一个为Private,则此Tuple的Access Level为Private

Function Types

一个Function Type的Access Level不能高于它的参数,返回值的最小的权限

1
2
3
4
5
6
7
8
9
//错误写法,因为(SomeInternalClass, SomePrivateClass)是Private,所以someFunction()也是Private的
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
}
//正确写法
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
}

对于Function,如果不是internal,必须显示的写清楚的它的Access Level

Enumeration Types

Enumeration Types只能给Enumeration Types定义Acess Level,不能给内部属性定义

1
2
3
4
5
6
7
//所有都是public的
public enum CompassPoint {
case north
case south
case east
case west
}

Enumeration的Raw Values and Associated Values的Access Type至少要比enum一样或高,不能低于enum

Nested Types

  • Private Class中的Nested Types的Access Level默认为private
  • file-private Class中的Nested Types的Access Level默认为File-Private
  • public 或 internalClass中的Nested Types的Access Level默认为Internal

Subclassing

子类的Access Level权限不能高于父类

1
2
3
4
5
6
7
8
9
10
11
public class A {
fileprivate func someMethod() {}
}
//B的Access Level不能高于A
internal class B: A {
//override方法可以高于父类的方法
override internal func someMethod() {
super.someMethod()
}
}
  • 对于子类本身,它的权限不能高于父类
  • 对于子类重写父类的方法,它的权限可以高于父类方法本身,但不能超过子类本身的权限范围(如子类是internal的,方法不能是public,超过了internal范围)

Constants, Variables, Properties, and Subscripts

一个constant, variable, or property它被定义的权限级别,不能高于Type本身

1
2
3
4
5
6
//error SomePrivateClass是Private的,所以privateInstance只能不高于Prirvate
public var privateInstance:SomePrivateClass = SomePrivateClass()
//正确
private var privateInstance:SomePrivateClass = SomePrivateClass()

Getters and Setters

Getters and Setters默认访问级别与它们的properties一样

你可以显式的修改为级别更低,但不能更高

Initializers

Initializers的权限级别不能高于它的Type,但required init必须与它的Type一样

Default Initializers

对于Default Initializers,它的Access Level默认与Type一样

Default Memberwise Initializers for Structure Types

对于Structure Type的Default Memberwise Initializers,按如下规则

  • 如果任意一属性为最低为private,则Default Memberwise Initializers为private
  • 如果任意一属性最低为file-private,则Default Memberwise Initializers同样为file-private
  • 其它情况下,Default Memberwise Initializers为internal

Protocols

如果给Protocols定义了Access Levels,则Protocol中的所有方法,属性拥有同一Access Level

1
2
3
fileprivate protocol A {
var a:Int { get set } //fileprivate
}

Protocols继承另一Protocols,Aceess Level不能更高

1
2
3
4
5
6
7
8
fileprivate protocol A {
var a:Int { get set } //fileprivate
}
//Error,不能比fileprivate更高
public protocol B : A {
}

实现Protocol的Type的Access Level可以与Protocol不一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fileprivate protocol A {
var a:Int { get set } //fileprivate
}
//这个是允许的
public class Person : A {
var a:Int = 0
}
//以protocol定义时,它的权限不能高于fileprivate
fileprivate let person:A = Person()
//但以Person类定义时,它受类的Acess Level控制
public let person2:Person = person as! Person

也就是对于实现实现的类,Acess Level不受Protocol控制

Extensions

Extensions的级别与Type定义的级别一致

你也可以显式的修改Extensions级别的定义,一旦修改与原Type不同,则Extensions定义的属性和方法就受你显式定义的Extensions级别的影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Person {
var name:String
init(name:String,age:Int) {
self.name = name
}
}
//一样是public
extension Person {
func hello() -> String{
return "hello,我是\(self.name)"
}
}
//改为private
private extension Person {
var age:Int {
return 0
}
}