Swift基础语法(十三)访问控制

Swift基础学习文章汇总

本文介绍Swift中访问权限控制,重要理解不同实体之间的权限影响,以及常见的访问级别规则

主要内容:

  1. 访问权限控制类型认识
  2. 使用准则
  3. 常见访问级别

1. 访问权限控制类型认识

Swift中也提供了多种访问权限,与其他语言不一样的是,他主要基于文件模块来区分权限,并且还定义了多种使用准则来判断不同实体之间的权限是如何影响的。

类型

  • open:
  • public:
  • internal:
  • fileprivate
类型 说明
open: 允许在定义实体的模块、其他模块中访问,允许其他模块进行继承、重写(open只能用在类、类成员上)
public: 允许在定义实体的模块、其他模块中访问,不允许其他模块进行继承、重写
internal: 只允许在定义实体的模块中访问,不允许在其他模块中访问
fileprivate: 只允许在定义实体的源文件中访问
private: 只允许在定义实体的封闭声明中访问

注意:

  1. 一个模块就代表一个可执行文件
  2. 需要注意,默认的权限不是public,而public的可以允许其他模块访问
  3. 默认权限是internal,全模块中使用

2. 使用准则

准则:

  • 对一个实体进行访问使用时,该实体相关的实体也必须可以被访问
  • 访问权限的本质是作用域范围
  • 类的成员的权限是跟着类的权限走的,但是其本质是作用域跟着走,而非表面的权限关键字

相互影响实体的访问:

准则.png

2.1 成员影响类型

2.1.1 元祖类型

代码:

/*
 1、成员影响类型
 */
//1.1 元组
internal struct Dog {}
fileprivate class Person {}

// (Dog, Person)的访问级别是fileprivate
fileprivate var data1: (Dog, Person)
//手动设置类型,但此时二者等价,因为私有的范围刚好就是fileprivate
private var data2: (Dog, Person)

说明:

  • 元祖类型的访问级别取决于所有成员中成员类型的访问级别最低那个
  • 因为我要访问这个元祖时,其相关实体也必须可以访问
  • 此时的private和fileprivate作用域范围是一样的,因为私有的范围刚好就是本文件,也就是fileprivate

2.1.2 泛型类型

代码:

//1.2 泛型
internal class Car {}
fileprivate class Dog {}
public class Person<T1, T2> {}

// Person<Car, Dog>的访问级别是fileprivate
fileprivate var p = Person<Car, Dog>()

说明:

  • 泛型类型的访问级别是类型的访问级别以及所有泛型类型参数的访问级别中最低的那个
  • 包括类型的访问级别和泛型类型参数的访问级别

2.1.3 总结

  • 某些类型的访问权限被其他实体所默认决定,比如这里的元祖类型、泛型类型
  • 其访问权限的作用域范围要小于等于被其决定的实体的访问权限,因此这里的元组类型不能大于fileprivate(否则元组就不能使用Person了)
  • 使用了自己的实体的权限不能大于自己,否则外界可能无法使用 自己

2.2 类型影响成员

类型的访问级别会影响成员(属性、方法、初始化器、下标)、嵌套类型的默认访问级别。这里最为重要的是理解作用域,成员的作用域默认情况下是和类型的作用域相等

一般情况:
这里都说的是一般情况下,因为在不同的情况下其作用域是不太一样的
准则:

  • 一般情况下,类型为private或fileprivate,那么成员\嵌套类型默认也是private或fileprivate
  • 一般情况下,类型为internal或public,那么成员\嵌套类型默认是internal

代码:

/*
 2、类型影响成员
 */
public class PublicClass {
    public var p1 = 0 // public
    var p2 = 0 // internal
    fileprivate func f1() {} // fileprivate
    private func f2() {} // private
}

class InternalClass { // internal
    var p = 0 // internal
    fileprivate func f1() {} // fileprivate
    private func f2() {} // private
}

说明:

  • 类型为public默认情况下子成员权限为internal
  • 如果显式去写,就不用默认的

特殊情况:
案例一:

作用域.png

说明:

  • 定义在函数内会报错,因为子类的作用域大于父类的作用域(子类的作用域是本文件,而父类的作用域是函数体)
  • 定义在全局不会报错,是因为他们的作用域刚好是一样的(子类的作用域是本文件,父类的作用域是私有的,也刚好是本文件)
  • 这证明了重点是看作用域,而不能仅仅通过表面上的权限关键字来决定

案例二:
代码:

//age和run()与Dog结构体的作用域范围一样,是当前文件
private struct Dog {
    var age: Int = 0
    func run() {}
}
fileprivate struct Person {
    var dog: Dog = Dog()
    mutating func walk() {
        dog.run()
        dog.age = 1
    } 
}

说明:

  • Dog的权限为private,按理说其成员也是private,无法被外界访问,但是这里并不会报错
  • 此时在全局区定义Dog,它的访问权限是private,其实是属于fileprivate,所以此时其属性也默认为fileprivate,千万要注意并不是private
  • 也就是说类的成员的权限是跟着类的权限走的,但是其本质是作用域跟着走,而非表面的权限关键字

3. 常见访问级别

3.1 get、get的访问级别

代码:

/*
 3、getter、setter的访问级别
 */
fileprivate(set) public var num = 10//全局变量
class Person {
    private(set) var age = 0//只将set设置为私有的
    fileprivate(set) public var weight: Int {//只将set设置为fileprivate的
        set {}
        get { 10 }
    }
    internal(set) public subscript(index: Int) -> Int {//只将set设置为internal的
        set {}
        get { index }
    }
}

说明:

  1. getter、setter默认自动接收它们所属环境的访问级别
  2. 可以给setter单独设置一个比getter更低的访问级别,用以限制写的权限

3.2 初始化器的访问级别

如果一个public类想在另一个模块调用编译生成的默认无参初始化器,必须显式提供public的无参初始化器,因为public类的默认初始化器是internal级别

如果结构体有private\fileprivate的存储实例属性,那么它的成员初始化器也是private\fileprivate,而且只要有一个成员是private,那么其成员初始化器就是private,否则默认就是internal

required初始化器 ≥ 它的默认访问级别

初始化器的访问级别.png

说明:

  • init使用required,那么这个init必须大于等于它的默认访问级别,也就是说它的访问级别是不能小于默认的internal的

3.3 枚举和协议实现的访问级别

枚举和协议都不能单独设置其成员的权限,其作用域与枚举、协议保持一致
协议实现的访问级别必须 ≥ 类型的访问级别,或者 ≥ 协议的访问级别
代码:

fileprivate protocol Runnable {
    func run()
}

public class Person : Runnable {
    fileprivate func run() {}//等于协议的访问级别
}
协议实现访问级别.png

说明:

  • 协议的实现要大于等于他们二者最小的权限
  • 我们真正使用的是这个run(),所以与其相关的其他实体必须也可以访问

3.4 扩展的访问级别

准则:

  • 如果有显式设置扩展的访问级别,扩展添加的成员自动接收扩展的访问级别
  • 如果没有显式设置扩展的访问级别,扩展添加的成员的默认访问级别,跟直接在类型中定义的成员一样
  • 可以单独给扩展添加的成员设置访问级别
  • 不能给用于遵守协议的扩展显式设置扩展的访问级别
  • 在同一文件中的扩展,可以写成类似多个部分的类型声明

代码:

/*
 6、扩展的访问级别
 */

public class Person {
    private func run0() {}
    private func eat0() {
        run1()
    }
}
extension Person {
    private func run1() {}
    private func eat1() {
        run0()
    }
}
extension Person {
    private func eat2() {
        run1()
    }
}

说明:

  1. 在原本的声明中声明一个私有成员,可以在同一文件的扩展中访问它
  2. 在扩展中声明一个私有成员,可以在同一文件的其他扩展中、原本声明中访问它

3.5 重写的访问级别

子类和父类的访问级别.png
重写父类私有成员.png

说明:

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

推荐阅读更多精彩内容