Swift 访问控制

简介: Swift 访问控制

访问控制可以限定其他源文件或模块中代码对你代码的访问级别。

你可以明确地给单个类型(类、结构体、枚举)设置访问级别,也可以给这些类型的属性、函数、初始化方法、基本类型、下标索引等设置访问级别。

协议也可以被限定在一定的范围内使用,包括协议里的全局常量、变量和函数。

访问控制基于模块与源文件。

模块指的是以独立单元构建和发布的 Framework 或 Application。在 Swift 中的一个模块可以使用 import 关键字引入另外一个模块。

源文件是单个源码文件,它通常属于一个模块, 源文件可以包含多个类和函数 的定义。

Swift 为代码中的实体提供了四种不同的访问级别:public、internal、fileprivate、private

访问级别 定义
public 可以访问自己模块中源文件里的任何实体,别人也可以通过引入该模块来访问源文件里的所有实体。
internal 可以访问自己模块中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。
fileprivate 文件内私有,只能在当前源文件中使用。
private 只能在类中访问,离开了这个类或者结构体的作用域外面就无法访问。

public 为最高级访问级别,private 为最低级访问级别。

语法

通过修饰符public、internal、fileprivate、private来声明实体的访问级别:

实例

public class SomePublicClass {}internal class SomeInternalClass {}fileprivate class SomeFilePrivateClass {}private class SomePrivateClass {} public var somePublicVariable = 0internal let someInternalConstant = 0fileprivate func someFilePrivateFunction() {}private func somePrivateFunction() {}

除非有特殊的说明,否则实体都使用默认的访问级别 internal。

未指定访问级别默认为 internal

class SomeInternalClass {}              // 访问级别为 internallet someInternalConstant = 0            // 访问级别为 internal


函数类型访问权限

函数的访问级别需要根据该函数的参数类型和返回类型的访问级别得出。

下面的例子定义了一个名为someFunction全局函数,并且没有明确地申明其访问级别。

func someFunction() -> (SomeInternalClass, SomePrivateClass) {

   // 函数实现

}

函数中其中一个类 SomeInternalClass 的访问级别是 internal,另一个 SomePrivateClass 的访问级别是 private。所以根据元组访问级别的原则,该元组的访问级别是 private(元组的访问级别与元组中访问级别最低的类型一致)。

因为该函数返回类型的访问级别是 private,所以你必须使用 private 修饰符,明确的声明该函数:

private func someFunction() -> (SomeInternalClass, SomePrivateClass) {

   // 函数实现

}

将该函数申明为 public 或 internal,或者使用默认的访问级别 internal 都是错误的,因为如果这样你就无法访问 private 级别的返回值。


枚举类型访问权限

枚举中成员的访问级别继承自该枚举,你不能为枚举中的成员单独申明不同的访问级别。

实例

比如下面的例子,枚举 Student 被明确的申明为 public 级别,那么它的成员 Name,Mark 的访问级别同样也是 public:

实例

public enum Student {    case Name(String)    case Mark(Int,Int,Int)} var studDetails = Student.Name("Swift")var studMarks = Student.Mark(98,97,95) switch studMarks {case .Name(let studName):     print("学生名: \(studName).")case .Mark(let Mark1, let Mark2, let Mark3):     print("学生成绩: \(Mark1),\(Mark2),\(Mark3)")}

以上程序执行输出结果为:

学生成绩: 98,97,95


子类访问权限

子类的访问级别不得高于父类的访问级别。比如说,父类的访问级别是 internal,子类的访问级别就不能申明为 public。

实例

public class SuperClass {    fileprivate func show() {        print("超类")    }} // 访问级别不能高于超类 public > internalinternal class SubClass: SuperClass  {    override internal func show() {        print("子类")    }} let sup = SuperClass()sup.show() let sub = SubClass()sub.show()

以上程序执行输出结果为:

超类

子类


常量、变量、属性、下标访问权限

常量、变量、属性不能拥有比它们的类型更高的访问级别。

比如说,你定义一个public级别的属性,但是它的类型是private级别的,这是编译器所不允许的。

同样,下标也不能拥有比索引类型或返回类型更高的访问级别。

如果常量、变量、属性、下标索引的定义类型是private级别的,那么它们必须要明确的申明访问级别为private:

private var privateInstance = SomePrivateClass()


Getter 和 Setter访问权限

常量、变量、属性、下标索引的Getters和Setters的访问级别继承自它们所属成员的访问级别。

Setter的访问级别可以低于对应的Getter的访问级别,这样就可以控制变量、属性或下标索引的读写权限。

实例

class Samplepgm {    fileprivate var counter: Int = 0{        willSet(newTotal){            print("计数器: \(newTotal)")        }        didSet{            if counter > oldValue {                print("新增加数量 \(counter - oldValue)")            }        }    }} let NewCounter = Samplepgm()NewCounter.counter = 100NewCounter.counter = 800

counter 的访问级别为 fileprivate,在文件内可以访问。

以上程序执行输出结果为:

计数器: 100

新增加数量 100

计数器: 800

新增加数量 700


构造器和默认构造器访问权限

初始化

我们可以给自定义的初始化方法申明访问级别,但是要不高于它所属类的访问级别。但必要构造器例外,它的访问级别必须和所属类的访问级别相同。

如同函数或方法参数,初始化方法参数的访问级别也不能低于初始化方法的访问级别。

默认初始化方法

Swift为结构体、类都提供了一个默认的无参初始化方法,用于给它们的所有属性提供赋值操作,但不会给出具体值。

默认初始化方法的访问级别与所属类型的访问级别相同。

实例

在每个子类的 init() 方法前使用 required 关键字声明访问权限。

实例

class classA {    required init() {        var a = 10        print(a)    }} class classB: classA {    required init() {        var b = 30        print(b)    }} let res = classA()let show = classB()

以上程序执行输出结果为:

10

30

10


协议访问权限

如果想为一个协议明确的申明访问级别,那么需要注意一点,就是你要确保该协议只在你申明的访问级别作用域中使用。

如果你定义了一个public访问级别的协议,那么实现该协议提供的必要函数也会是public的访问级别。这一点不同于其他类型,比如,public访问级别的其他类型,他们成员的访问级别为internal。

实例

public protocol TcpProtocol {    init(no1: Int)} public class MainClass {    var no1: Int // local storage    init(no1: Int) {        self.no1 = no1 // initialization    }} class SubClass: MainClass, TcpProtocol {    var no2: Int    init(no1: Int, no2 : Int) {        self.no2 = no2        super.init(no1:no1)    }         // Requires only one parameter for convenient method    required override convenience init(no1: Int)  {        self.init(no1:no1, no2:0)    }} let res = MainClass(no1: 20)let show = SubClass(no1: 30, no2: 50) print("res is: \(res.no1)")print("res is: \(show.no1)")print("res is: \(show.no2)")

以上程序执行输出结果为:

res is: 20

res is: 30

res is: 50


扩展访问权限

你可以在条件允许的情况下对类、结构体、枚举进行扩展。扩展成员应该具有和原始类成员一致的访问级别。比如你扩展了一个公共类型,那么你新加的成员应该具有和原始成员一样的默认的internal访问级别。

或者,你可以明确申明扩展的访问级别(比如使用private extension)给该扩展内所有成员申明一个新的默认访问级别。这个新的默认访问级别仍然可以被单独成员所申明的访问级别所覆盖。


泛型访问权限

泛型类型或泛型函数的访问级别取泛型类型、函数本身、泛型类型参数三者中的最低访问级别。

实例

public struct TOS<T> {    var items = [T]()    private mutating func push(item: T) {        items.append(item)    }         mutating func pop() -> T {        return items.removeLast()    }} var tos = TOS<String>()tos.push("Swift")print(tos.items) tos.push("泛型")print(tos.items) tos.push("类型参数")print(tos.items) tos.push("类型参数名")print(tos.items)let deletetos = tos.pop()

以上程序执行输出结果为:

["Swift"]

["Swift", "泛型"]

["Swift", "泛型", "类型参数"]

["Swift", "泛型", "类型参数", "类型参数名"]


类型别名

任何你定义的类型别名都会被当作不同的类型,以便于进行访问控制。一个类型别名的访问级别不可高于原类型的访问级别。

比如说,一个private级别的类型别名可以设定给一个public、internal、private的类型,但是一个public级别的类型别名只能设定给一个public级别的类型,不能设定给internal或private 级别的类型。

注意:这条规则也适用于为满足协议一致性而给相关类型命名别名的情况。

实例

public protocol Container {    typealias ItemType    mutating func append(item: ItemType)    var count: Int { get }    subscript(i: Int) -> ItemType { get }} struct Stack<T>: Container {    // original Stack<T> implementation    var items = [T]()    mutating func push(item: T) {        items.append(item)    }         mutating func pop() -> T {        return items.removeLast()    }         // conformance to the Container protocol    mutating func append(item: T) {        self.push(item)    }         var count: Int {        return items.count    }         subscript(i: Int) -> T {        return items[i]    }} func allItemsMatch<     C1: Container, C2: Container    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>     (someContainer: C1, anotherContainer: C2) -> Bool {        // check that both containers contain the same number of items        if someContainer.count != anotherContainer.count {            return false        }                 // check each pair of items to see if they are equivalent        for i in 0..<someContainer.count {            if someContainer[i] != anotherContainer[i] {                return false            }        }                 // all items match, so return true        return true} var tos = Stack<String>()tos.push("Swift")print(tos.items) tos.push("泛型")print(tos.items) tos.push("Where 语句")print(tos.items) var eos = ["Swift", "泛型", "Where 语句"]print(eos)

以上程序执行输出结果为:

["Swift"]

["Swift", "泛型"]

["Swift", "泛型", "Where 语句"]

["Swift", "泛型", "Where 语句"]

目录
相关文章
|
4天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
7天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
4天前
|
人工智能 运维 双11
2024阿里云双十一云资源购买指南(纯客观,无广)
2024年双十一,阿里云推出多项重磅优惠,特别针对新迁入云的企业和初创公司提供丰厚补贴。其中,36元一年的轻量应用服务器、1.95元/小时的16核60GB A10卡以及1元购域名等产品尤为值得关注。这些产品不仅价格亲民,还提供了丰富的功能和服务,非常适合个人开发者、学生及中小企业快速上手和部署应用。
|
13天前
|
人工智能 弹性计算 文字识别
基于阿里云文档智能和RAG快速构建企业"第二大脑"
在数字化转型的背景下,企业面临海量文档管理的挑战。传统的文档管理方式效率低下,难以满足业务需求。阿里云推出的文档智能(Document Mind)与检索增强生成(RAG)技术,通过自动化解析和智能检索,极大地提升了文档管理的效率和信息利用的价值。本文介绍了如何利用阿里云的解决方案,快速构建企业专属的“第二大脑”,助力企业在竞争中占据优势。
|
14天前
|
自然语言处理 数据可视化 前端开发
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
合合信息的智能文档处理“百宝箱”涵盖文档解析、向量化模型、测评工具等,解决了复杂文档解析、大模型问答幻觉、文档解析效果评估、知识库搭建、多语言文档翻译等问题。通过可视化解析工具 TextIn ParseX、向量化模型 acge-embedding 和文档解析测评工具 markdown_tester,百宝箱提升了文档处理的效率和精确度,适用于多种文档格式和语言环境,助力企业实现高效的信息管理和业务支持。
3936 2
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
|
4天前
|
算法 安全 网络安全
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
2024阿里云11.11金秋云创季活动火热进行中,活动月期间(2024年11月01日至11月30日)通过折扣、叠加优惠券等多种方式,阿里云WoSign SSL证书实现优惠价格新低,DV SSL证书220元/年起,助力中小企业轻松实现HTTPS加密,保障数据传输安全。
499 3
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
|
10天前
|
安全 数据建模 网络安全
2024阿里云双11,WoSign SSL证书优惠券使用攻略
2024阿里云“11.11金秋云创季”活动主会场,阿里云用户通过完成个人或企业实名认证,可以领取不同额度的满减优惠券,叠加折扣优惠。用户购买WoSign SSL证书,如何叠加才能更加优惠呢?
985 3
|
8天前
|
机器学习/深度学习 存储 人工智能
白话文讲解大模型| Attention is all you need
本文档旨在详细阐述当前主流的大模型技术架构如Transformer架构。我们将从技术概述、架构介绍到具体模型实现等多个角度进行讲解。通过本文档,我们期望为读者提供一个全面的理解,帮助大家掌握大模型的工作原理,增强与客户沟通的技术基础。本文档适合对大模型感兴趣的人员阅读。
397 16
白话文讲解大模型| Attention is all you need
|
8天前
|
算法 数据建模 网络安全
阿里云SSL证书2024双11优惠,WoSign DV证书220元/年起
2024阿里云11.11金秋云创季火热进行中,活动月期间(2024年11月01日至11月30日),阿里云SSL证书限时优惠,部分证书产品新老同享75折起;通过优惠折扣、叠加满减优惠券等多种方式,阿里云WoSign SSL证书将实现优惠价格新低,DV SSL证书220元/年起。
560 5
|
4天前
|
安全 网络安全
您有一份网络安全攻略待领取!!!
深入了解如何保护自己的云上资产,领取超酷的安全海报和定制鼠标垫,随时随地提醒你保持警惕!
693 1
您有一份网络安全攻略待领取!!!