美文网首页
Swift进阶(十六)访问控制

Swift进阶(十六)访问控制

作者: Jax_YD | 来源:发表于2021-01-27 17:27 被阅读0次

访问控制(Access Control)

  • 在访问权限控制这块,Swift提供了5个不同的访问级别(以下是从高到低排列,实体指被访问级别修饰的内容):
    open:允许在定义实体的模块、其他模块中访问,允许其他模块进行继承、重写(open只能用在类、类成员上)
    public:允许在定义实体的模块、其他模块中访问,不允许其他模块进行继承、重写
    internal:只允许在定义实体的模块中访问,不允许在其他模块中访问
    fileprivate:只允许在定义实体的源文件中访问
    private:只允许在定义实体的封闭声明中访问

  • 绝大部分实体默认都是internal级别


访问级别的使用准则

  • 一个实体不可以被更低访问级别的实体定义,如下:
    □ 变量\常量类型 \color{orange}{≥} 变量\常量
    □ 参数类型、返回值类型 \color{orange}{≥} 函数
    □ 父类 \color{orange}{≥} 子类
    □ 父协议 \color{orange}{≥} 子协议
    □ 原类型 \color{orange}{≥} typealias
    □ 原始值类型、关联值类型 \color{orange}{≥} 枚举类型
    □ 定义类型A时用到的其他类型 \color{orange}{≥} 类型A
    □ ......

下面我们来解释一下上面面的规则:

  • 变量\常量类型 \color{orange}{≥} 变量\常量

    image.png
    上面我们讲过struct Point {}的默认级别是internal,同样p1、p2、p_1、p_2的默认级别也是internal,然而struct Point_1 {}的级别是private小于internal。那么如果说外界访问p_1、p_2时,又没有权限访问Point_1,这就是矛盾的,所以会报错。
  • 参数类型、返回值类型 \color{orange}{≥} 函数

    image.png
  • 父类 \color{orange}{≥} 子类

    image.png
    能访问到子类必然也要能访问到父类,所以父类的级别要大于等于子类
  • 父协议 \color{orange}{≥} 子协议

    image.png
  • 原类型 \color{orange}{≥} typealias

    image.png
  • 原始值类型、关联值类型 \color{orange}{≥} 枚举类型

    image.png
  • 定义类型A时用到的其他类型 \color{orange}{≥} 类型A

    image.png

元组类型

  • 元组类型的访问级别,跟所有成员类型中最底的级别保持一致
internal class Dog {}
fileprivate class Animal {}

fileprivate var data: (Dog, Animal) // (Dog, Animal)的访问级别是fileprivate

泛型类型

  • 泛型类型的访问级别是 \color{orange}{类型的访问级别} 以及 \color{orange}{所有泛型类型参数的访问级别} 中最底的那个
internal class Dog {}
fileprivate class Cat {}
public class Animal<T1, T2> {}

fileprivate var animal = Animal<Dog, Cat>() // Animal<Dog, Cat>()的访问级别是fileprivate

成员、嵌套类型

  • 类型的访问级别会影响成员(属性、方法、初始化器、下标)、嵌套类型的访问级别
    □ 一般情况下,类型为privatefileprivate,那么成员\嵌套类型默认也是privatefileprivate
    □ 一般情况下,类型为internalpublic,那么成员\嵌套类型默认是internal
private class Person {
    var name: String = "" // private
    var age: Int = 0 // private
    
    enum city { // private
        case beijing
        case nanjing
    }
}

public class Animal {
    public var type = 0 // public
    var name = "" // internal
    fileprivate func fun1() {} // fileprivate
    private func fun2() {} // private
}

这里大家要注意一个\color{orange}{作用域}的问题,比如上面Person的嵌套类型city的级别是private,那么city内部成员的级别也就是private;在这种情况下Person能否访问city的内部成员呢?
答案是:可以的
因为city内部成员没有单独显示声明级别,那么其所对应的级别跟city保持一致也是private,其访问级别作用域也保持一致,也是Person。所以可以访问。

同样的,在全局作用域中fileprivateprivate的修饰没有什么区别,作用域都是当前文件。如下代码:

image.png

成员的重写

  • 子类重写成员的访问级别必须 \color{orange}{≥} 子类的访问级别,或者 \color{orange}{≥} 父类被重写成员的访问级别
  • 父类的成员不能被成员作用域外定义的子类重写

正常情况下,我们是这样写的:

class Person {
    var age: Int = 0
}

class Student: Person {
    override var age: Int {
        set {}
        get {13}
    }
}

第一种情况:降低重写后的age访问级别

image.png
第二种情况:降低重写前的age访问级别
image.png
此时age的作用域只存在于Person内部,所以如果我们想在子类中重写age,我们除了可以增加age的权限之外,还可以把子类写在Person内部
image.png

getter、setter

  • gettersetter默认自动接收它们所属环境的访问级别
  • 可以给setter单独设置一个比getter更低的访问级别,用以限制写的权限
    注意:getter的权限不能比setter
// num可以在其他实体中被访问,但是只能在当前文件中被修改
fileprivate(set) public var num = 10

class Person {
    private(set) var name = "Aaron"
    fileprivate(set) public var age: Int {
        set {}
        get { 10 }
    }
}

初始化器

  • 如果一个public类想在另一个模块调用编译生成的默认无参初始化器,必须\color{orange}{显示提供} public无参初始化器
    □ 因为public类的默认初始化器是internal级别(在写一些提供给别人用的库的时候会用到)
  • required初始化器 \color{orange}{≥} 它的默认访问级别
  • 如果结构体有private\fileprivate的存储实例属性,那么它的\color{orange}{成员初始化器}也是private\fileprivate
    □ 否则默认是internal
    image.png

枚举类型的case

  • 不能给enum的每个case单独设置访问级别
  • 每个case自动接收enum的访问级别
    注意:public enum定义的case也是public,这一点与上面的结构体、类有一定的区别
    image.png

协议

  • 协议中\color{orange}{定义的要求},自动接收协议的访问级别,不能单独设置访问级别
    public协议定义的要求也是public,这一点与上面的结构体、类有一定的区别
    image.png
  • 协议实现的访问级别必须 \color{orange}{≥} 类型的访问级别,或者 \color{orange}{≥} 协议的访问级别。也就是说要 $\color{orange}{≥} 两者中最小的那个。
    image.png
    大家注意,下面的代码也是不行的,因为public修饰类的时候,类里面的成员默认是internal
    image.png

扩展

  • 如果有显示设置扩展的访问级别,扩展添加的成员自动接收扩展的访问级别

  • 如果没有显示设置扩展的访问级别,扩展添加的成员默认访问级别,跟直接在类型中定义的成员一样

  • 可以单独给扩展中添加的成员设置访问级别

  • 不能给遵守协议的扩展显示设置扩展的访问级别


    image.png
  • 在同一个文件中的扩展,可以写成类似多个部分的类型声明
    □ 在原本的声明中,声明一个私有成员,可以在同一个文件的扩展中访问它。
    □ 在扩展中声明一个私有成员,也可以在同一个文件的其他扩展中,或者原本的声明中访问它。

    image.png

相关文章

  • Swift进阶(十六)访问控制

    访问控制(Access Control) 在访问权限控制这块,Swift提供了5个不同的访问级别(以下是从高到低排...

  • Swift进阶11:访问控制

    访问控制限制其他源文件和模块对你的代码的访问。这个特性允许你隐藏代码的实现细节,并指定一个偏好的接口让其他代码可以...

  • Swift进阶:访问控制权限

    swift 进阶之路:学习大纲[https://www.jianshu.com/p/115367c3eefd] 本...

  • Swift 3必看:新的访问控制fileprivate和open

    Swift 3必看:新的访问控制fileprivate和open Swift 3必看:新的访问控制filepriv...

  • 十六、访问控制

    访问控制 访问控制 在访问权限控制这块,Swift提供了5个不同的访问级别(以下从高到低排列) open:允许在定...

  • iOS学习笔记49-Swift(九)访问控制

    一、Swift的访问控制 Swift中的访问控制模型基于模块和源文件这两个概念 模块指的是Framework或Ap...

  • Swift 访问控制

    Swift’s access control model is based on the concept of m...

  • Swift:访问控制

    中文文档 一、模块和源文件 Swift 中的访问控制模型基于模块和源文件这两个概念。 模块指的是独立的代码单元,框...

  • Swift: 访问控制

    和其他高级语言一样Swift中也有访问控制,在Swift中提供了private、internal、public三种...

  • Swift 访问控制

    模组 Module 模组 是代码分布的单一单元。比如一个被作为一个单位编译和发布,别且可以被其它模组用import...

网友评论

      本文标题:Swift进阶(十六)访问控制

      本文链接:https://www.haomeiwen.com/subject/jmfnzktx.html