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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容