访问控制

2019-09-25  本文已影响0人  纳兰沫

访问控制 Access Control

访问级别

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

实体是被访问级别修饰的内容
绝大部分实体都是internal 修饰的

访问级别的使用准则

一个实体不可以被更低访问级别的实体定义
a.变量/常量类型 >=  变量/常量
b.参数类型 返回值类型 >= 函数
c.父类 >= 子类
d.父协议 >= 子协议
e.原类型 >= typealias
f.原始值类型 关联值类型 >= 枚举类型
g.定义类型A用到的其他类型 >= 类型A

元祖类型访问级别

元祖类型的访问级别是所有成员类型最低的那个

泛型类型的访问级别

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

成员 嵌套类型访问级别

类型访问级别会影响成员(属性 方法 初始化器 下标) 嵌套类型的默认访问级别

一般情况下 类型为private 或 filePrivate 那么成员/嵌套类型也是private 或 filePrivate
fileprivate class Person {
    
    var age = 0
    func run() {}
    
    enum Season {
        case spring,summer
    }
}
一般情况下 类型为internal 或 public 那么成员/嵌套类型是internal
private class Person {
    
}

fileprivate class student: Person {
    
}

子类重写的成员访问级别 >= 父类的成员访问级别
直接在全局作用域下定义的private相当于filePrivate 那么里面包含的就相当于filePrivate 修饰

getter setter 访问级别

getter setter 默认自动接收他们所属环境的访问级别

可以给setter单独设置一个比getter更低的访问级别 用于限制写的权限

fileprivate(set) public var num = 10
class Person {
    private(set) var age = 0
    fileprivate(set) public var weight: Int {
        
        set{}
        get{
            return 10
        }
    }
    internal(set) public subscript(index: Int) -> Int {
        set{}
        get{
            return index
        }
    }
}

初始化器

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

requirder初始化器必须要跟他所属类拥有相同的访问级别

如果结构体有为private 或 filePrivate的存储实例属性 那么他的成员初始化器是为private 或 filePrivate

枚举类型的case访问级别

不能给enum的每个case单独设置访问级别
每个case自动接收enum的访问级别
public修饰enum 定义的case也是public

协议的访问级别

协议中定义的要求自动接收协议的访问级别 不能单独设置访问级别

public协议定义的要求也是public
协议实现的访问级别必须 >=  类型的访问级别  或者 >= 协议的访问级别

扩展的访问级别

- 如果有显示设置扩展的访问级别 扩展中添加的成员自动接受扩展的访问级别
- 如果没有显示设置扩展的访问级别 扩展中添加的成员的默认的访问级别 跟直接在类型中定义的成员一样
- 可以单独给扩展添加的成员设置访问级别
- 不能给用于遵守协议的扩展显示的设置扩展的访问级别
- 在同一文件中的扩展 可以写成类似多个部分的类型声明
  a.在原本的声明中声明一个私有成员 可以在同一文件的扩展中访问它
  b.在扩展中声明一个私有成员 可以在同一文件的其他扩展中 原本声明中访问它
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()
    }
}

将方法赋值给var/let

方法可以像函数那样 赋值给let或者var
struct Person {
    
    var age: Int
    func run(_ v: Int) {
        print("fun run",age,v)
    }
   
}

var p = Person(age: 10)
p.run(20)

var fn = Person.run
var fn2 = fn(Person(age: 10))
fn2(20)
struct Person {
    
    var age: Int
    func run(_ v: Int) {
        print("fun run",age,v)
    }
    static func run(_ v: Int) {
        print("static run",v)
    }
   
}

var fn = Person.run
fn(20)
struct Person {
    
    var age: Int
    func run(_ v: Int) {
        print("fun run",age,v)
    }
    static func run(_ v: Int) {
        print("static run",v)
    }
   
}

var fn:((Person) -> (Int) ->()) = Person.run
fn(Person(age: 10))(20)
上一篇 下一篇

猜你喜欢

热点阅读