25.访问控制 Access Control Swift官方文档——版纳的笔记

//: Playground - noun: a place where people can play

import UIKit

// # define: 访问控制限制其他源文件和模块对你的代码的访问。

// # 模块和源文件

// # 访问级别
// open:对所有模块开放访问、继承、子类重写.
// public:对所有模块开放访问.只能在其定义的模块中被继承或在其定义模块的子类中被重写.
// internal: 只允许实体被定义模块中的任意源文件访问、继承、子类重写。通常在定义应用程序或是框架的内部结构时使用。
// fileprivate: 只允许实体被定义模块中当前源文件访问、继承、子类重写。
// private: 实体的使用限制于封闭声明中。

// Swift 中的访问级别遵循一个总体指导准则:实体不可以被更低(限制更多)访问级别的实体定义。一个 public 的变量其类型的访问级别不能是 internal, file-private 或是 private,因为在使用 public 变量的地方可能没有这些类型的访问权限。一个函数不能比它的参数类型和返回类型访问级别高,因为函数可以使用的环境而其参数和返回类型却不能使用。
// 默认访问级别: internal
// 单元测试@testable???

// # 访问控制语法

// # 自定类型
// public 的类型默认拥有 internal 级别的成员,而不是 public。如果你想让其中的一个类型成员是 public 的,你必须按实示例代码指明。这个要求确保类型的面向公众的 API 是你选择的,并且可以避免将类型的内部工作细节公开成 API 的失误。
public class SomePublicClass {
    public var somePublicProperty = 0
    var someInternalProperty = 0
    fileprivate func someFilePrivateMethod() {}
    private func somePrivateMethod() {}
}
class SomeInternalClass {                                 // implicitly internal class
    var someInternalProperty = 0                      // implicitly internal class member
    fileprivate func someFilePrivateMethod() {}   // explicitly file-private class member
    private func somePrivateMethod() {}            // explicitly private class member
}
fileprivate class SomeFilePrivateClass {            // explicitly file-private class
    func someFilePrivateMethod() {}                 // implicitly file-private class member
    private func somePrivateMethod() {}           // explicitly private class member
}
private class SomePrivateClass {                     // explicitly private class
    func somePrivateMethod() {}                     // implicitly private class member
}

// 元组类型的访问级别会在使用的时候被自动推断出来,不需要显式指明。遵循最严格原理.

// 函数类型的访问级别由函数成员类型和返回类型中的最严格访问级别决定。如果函数的计算访问级别与上下文环境默认级别不匹配,你必须在函数定义时显式指出。
/*
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // function implementation goes here
}
*/

// 枚举中的独立成员自动使用该枚举类型的访问级别。你不能给独立的成员指明一个不同的访问级别。枚举定义中的原始值和关联值使用的类型必须有一个不低于枚举的访问级别。

// private 级别的类型中定义的嵌套类型自动为 private 级别。fileprivate 级别的类型中定义的嵌套类型自动为 fileprivate 级别。public 或 internal 级别的类型中定义的嵌套类型自动为 internal 级别。如果你想让嵌套类型是 public 级别的,你必须将其显式指明为 public。

// 子类不能高于父类的访问级别
public class A {
    fileprivate func someMethod() {}
}
internal class B: A {
    override internal func someMethod() {
        super.someMethod()
    } // 这是可以的.
}

// # 常量,变量,属性和下标
// 常量、变量、属性不能拥有比它们类型更高的访问级别。例如,你不能写一个public 的属性而它的类型是 private 的。类似的,下标也不能拥有比它的索引类型和返回类型更高的访问级别。

// # Getters和Setters
// 常量、变量、属性和下标的 getter 和 setter 自动接收它们所属常量、变量、属性和下标的访问级别。你可以给 setter 函数一个比相对应 getter 函数更低的访问级别以限制变量、属性、下标的读写权限。你可以通过在 var 和 subscript 的置入器之前书写 fileprivate(set) , private(set) , 或 internal(set) 来声明更低的访问级别。这个规则应用于存储属性和计算属性。即使你没有给一个存储属性书写一个明确的 getter 和 setter,Swift 会为你合成一个 getter 和 setter 以访问到存储属性的隐式存储。使用 fileprivate(set) , private(set) 和 internal(set) 可以改变这个合成的 setter 的访问级别,同样也可以改变计算属性的访问级别。
// numberOfEdits 在结构体外,包括结构体的扩展,都是只读属性
struct TrackedString {
    private(set) var numberOfEdits = 0 // getter还是默认的internal
    var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
}
var stringToEdit = TrackedString()
stringToEdit.value = "This string will be tracked."
stringToEdit.value += " This edit will increment numberOfEdits."
stringToEdit.value += " So will this one."
print("The number of edits is \(stringToEdit.numberOfEdits)")
public struct TrackedString2 {
    public private(set) var numberOfEdits = 0 // trick:设置 numberOfEdits 属性的getter方法为 public,setter 方法为 private 级别
    public var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
    public init() {}
}

// # 初始化器
// 可以给自定义初始化方法设置一个低于或等于它的所属的类的访问级别。必要初始化器必须和它所属类的访问级别一致。初始化器的参数类型不能比初始化方法的访问级别还低。
// 默认初始化方法和结构体的默认成员初始化器与所属类的访问级别一致,除非该类型定义为 public 。如果一个类定义为 public ,那么默认初始化方法为 internal 级别。

// # 协议
// 协议定义中的每一个要求的访问级别都自动设为与该协议相同。你不能将一个协议要求的访问级别设为与协议不同。这保证协议的所有要求都能被接受该协议的类型所见。
// 如果你定义了一个继承已有协议的协议,这个新协议最高与它继承的协议访问级别一致。例如你不能写一个 public 的协议继承一个 internal 的协议。
// 遵循了协议的类的访问级别取这个协议和该类的访问级别的最小者。如果这个类型是 public 级别的,它所遵循的协议是 internal 级别,这个类型就是 internal 级别的。必须确保该类按协议要求的实现方法与该协议的访问级别一致。例如,一个 public 的类遵循一个 internal 协议,该类的方法实现至少是 “internal” 的。

// # 扩展
// 在扩展中添加的任何类型成员都有着被扩展类型相同的访问权限。
// 可以显式标注扩展的访问级别(例如, private extension )已给扩展中的成员设置新的默认访问级别。不能给用于协议遵循的扩展显式标注访问权限修饰符。
// 扩展中可以访问原始定义的private

// # 泛型
// 最严格原理

// # 类型别名
// 任何你定义的类型同义名都被视为不同的类型以进行访问控制。一个类型同义名的访问级别不高于原类型。例如private可作为public 的alias

你可能感兴趣的:(25.访问控制 Access Control Swift官方文档——版纳的笔记)