Swift

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

2022-05-17  本文已影响0人  iOS之文一

Swift基础学习文章汇总

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

主要内容:

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

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

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

类型

类型 说明
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)

说明:

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 总结

2.2 类型影响成员

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

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

代码:

/*
 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
}

说明:

特殊情况:
案例一:

作用域.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
    } 
}

说明:

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

说明:

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

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

fileprivate protocol Runnable {
    func run()
}

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

说明:

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. 子类重写成员的访问级别要>= 子类的的访问级别,或者>= 父类被重写成员的访问级别
上一篇 下一篇

猜你喜欢

热点阅读