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

一、Swift的访问控制

Swift中的访问控制模型基于模块源文件这两个概念

模块:指的是FrameworkApp bundle。在Swift中,可以用import关键字引入自己的工程。

源文件:指的是Swift中的Swift File,就是编写Swift代码的文件,它通常是属于某一个模块。

Swift提供了三种不同的访问级别:

  • Public:【使用public修饰】【范围大】
    可以访问当前模块及其他模块中的任何实体(通常用于Framework
  • Internal:【使用internal修饰】【范围中】
    可以访问当前模块中的任何实体,但是在模块外无法访问,这是所有实体的默认访问级别(通常在一个单目标Application中不需要自行设置访问级别)
  • Private:【使用private修饰】【范围小】
    只能访问当前源文件中的实体,用作隐藏某些功能的实现细节

访问级别从低到高:Private < Internal < Public

访问控制的使用规则挺多的,我这里进行了概括:

  1. 【成员(属性和方法) <= 类】
  2. 【(常量、变量、属性、下标脚本) <= 类型】
  3. 【Setter <= Getter】
  4. 【required方法 == 类】【默认逐一构造函数 <= 所有成员】
  5. 【子类 <= 父类】【子协议 <= 父协议】
  6. 子类重写父类成员修改访问范围
  7. 【协议成员 == 协议】【类 >= 协议】【协议实现 >= 协议要求】
  8. 【元组 = Min(所有元素类型)】
  9. 【函数 = Min(参数类型,返回值类型)】
  10. 【枚举成员 == 枚举】【(原始值,关联值) >= 枚举】
  11. 【泛型类型 = Min(类类型,泛型参数)】
  12. 【类型别名 <= 原类型】

二、访问控制使用规则详解

1.【成员(属性和方法) <= 类】

/* 
    1.【成员(属性和方法) <= 类】
    如果你将类申明为private类,那么该类的所有成员的默认访问级别也会成为private
    如果你将类申明为public或者internal类,那么该类的所有成员默认访问级别是internal。
*/
public class SomePublicClass {          // 显示的public类
    public var somePublicProperty = 0    // 显示的public类成员
    var someInternalProperty = 0         // 隐式的internal类成员
    internal var someInternalProperty2 = 0 //显示的internal类成员
    private func somePrivateMethod() {}  // 显示的private类成员
}
internal class SomeInternalClass {        // 显示的internal类
    var someInternalProperty = 0         // 隐式的internal类成员
    private func somePrivateMethod() {}  // 显示的private类成员
    //Error:-> public var somePublicProperty = 0 
    
}
private class SomePrivateClass {        // 显示的private类
    var somePrivateProperty = 0          // 隐式的private类成员
    func somePrivateMethod() {}          // 隐式的private类成员
    //Error:-> public var somePublicProperty = 0 
    //Error:-> internal var someInternalProperty = 0
}

2.【(常量、变量、属性、下标脚本) <= 类型】

/* 2.【(常量、变量、属性、下标脚本) <= 自己类型】 */
private let somePrivate1 = SomePrivateClass() //变量为private <= 类型为private
private let somePrivate2 = SomeInternalClass()//变量为private <= 类型为internal
private let somePrivate3 = SomePublicClass()//变量为private <= 类型为public
//Error:internal let someInternal1 = SomePrivateClass() //变量internal大于类型private,错误
internal let someInternal2 = SomeInternalClass()//变量为internal <= 类型为internal
internal let someInternal3 = SomePublicClass()//变量为internal <= 类型为public
//Error:public let somePublic1 = SomePrivateClass() //变量public大于类型private,错误
//Error:public let somePublic2 = SomeInternalClass() //变量public大于类型internal,错误
public let somePublic3 = SomePublicClass()//变量为public <= 类型为public

3.【Setter <= Getter】

/* 3.【setter <= getter】,private(set)修饰将setter权限设置为private */
/* 
    这个规定适用于用作存储的属性或用作计算的属性。
    即使你不明确的申明存储属性的Getter、Setter,
    Swift也会隐式的为其创建Getter和Setter,用于对该属性进行读取操作。
*/
public class SetterPrivateClass {//该类可以在任何模块中使用
    private(set) var value = 0 //设置存储属性的setter为private
    //设置计算属性的setter属性为private
    private(set) var setPrivateProperty:Int {
        set{//此时setter为private,也就是只能在本文件中使用,其他文件无法使用
            value = newValue + 1
        }
        get{//getter默认为internal
            return value + 1
        }
    }
}

4.【required方法 == 类】【默认逐一构造函数 <= 所有成员】

/* 4.【required修饰的方法 == 类】,(结构体)【默认逐一构造函数 <= 所有成员】 */
protocol RequiredTestProtocol {
    //初始化构造器要求
    init(aprot: Int)
}
public class RequiredTestClass: RequiredTestProtocol {
    var aprot: Int //默认为internal
    //实现协议的初始化要求时,必须使用required关键字确保子类必须也得实现这个构造器
    public required init(aprot: Int) {//此时必须设置为public,因为默认是internal的
        self.aprot = aprot
    }
}
//该结构体的默认逐一构造方法为private,但默认构造方法还是internal
public struct StructInitTest{
    private var somePrivateProperty = 0
    internal var someInternalProperty = 0
    public var somePublicProperty = 0
}

5.【子类 <= 父类】【子协议 <= 父协议】

/* 5.【子类 <= 父类】,【子协议 <= 父协议】 */
private class PrivateSuperClass {  } //private父类
internal class InternalSuperClass {  }//internal父类
public class PublicSuperClass {  }//public父类
private class PrivateSubClass1:PrivateSuperClass {  } //子类private <= private父类
private class PrivateSubClass2:InternalSuperClass {  } //子类private <= internal父类
private class PrivateSubClass3:PublicSuperClass {  } //子类private <= public父类

//Error:internal class InternalSubClass1:PrivateSuperClass {  } //子类internal大于private父类,错误
internal class InternalSubClass2:InternalSuperClass {  } //子类internal <= internal父类
internal class InternalSubClass3:PublicSuperClass {  } //子类internal <= public父类

//Error:public class PublicSubClass1:PrivateSuperClass {  } //子类public大于private父类,错误
//Error:public class PublicSubClass2:InternalSuperClass {  } //子类public大于internal父类,错误
public class PublicSubClass3:PublicSuperClass {  } //子类public <= public父类

6. 子类重写父类成员修改访问范围

/* 6.不违反前面规则,子类可以通过重写父类方法来修改访问权限范围 */
public class OverrideSuperClass {
    private func someMethod() {}
}
internal class OverrideSubClass: OverrideSuperClass {
    override internal func someMethod() {
        super.someMethod()//子类和父类在同一个源文件中,所以可以访问super的someMethod()方法
    }
}

7.【协议成员 == 协议】【类 >= 协议】【协议实现 >= 协议要求】

/* 7.【协议所有必须实现的成员 == 协议】,【类 >= 协议】,【协议实现 >= 协议要求】 */
internal protocol InternalProtocol {
    //协议成员不可以添加访问控制关键字,默认等于协议的访问权限范围
    var someProperty:Int { get set }
    func someMethod()
}
//类必须大于或等于要遵循的协议
public class ProtocolTestClass:InternalProtocol {
    //Error:-> private var someProperty = 0 //协议实现必须大于或等于协议要求
    public var someProperty = 0
    internal func someMethod() {
        print("ProtocolTestClass someMethod")
    }
}

8.【元组 = Min(所有元素类型)】

/* 8.【元组 = Min(所有元素类型)】,注意是类型而不是变量 */
private var privateValue =  SomePrivateClass() //注意,看类型访问级别而不是变量访问级别
var internalValue =  SomeInternalClass()
var publicValue = SomePublicClass() //这里变量是internal的,但类型是public的
private let privateTupleValue = (privateValue, internalValue, publicValue)
internal let internalTupleValue = (internalValue, internalValue, publicValue)
public let publicTupleValue = (publicValue, publicValue, publicValue)

9.【函数 = Min(参数类型,返回值类型)】

/* 9.【函数 = Min(参数类型,返回值类型)】 */
private func someFunction(value:SomeInternalClass) -> SomePrivateClass {
    //函数体
    return SomePrivateClass()
}

10.【枚举成员 == 枚举】【(原始值,关联值) >= 枚举】

/* 10.【枚举成员 == 枚举】,枚举成员没法单独设置访问级别,【(原始值,关联值) >= 枚举】 */
private enum PrivateEnum {
    case PrivateEnumCase( SomePrivateClass )
    case InternalEnumCase( SomeInternalClass )
    case PublicEnumCase( SomePublicClass )
}
internal enum InternalEnum {
    //Error:-> case PrivateEnumCase( SomePrivateClass ) //关联值必须大于枚举
    case InternalEnumCase( SomeInternalClass )
    case PublicEnumCase( SomePublicClass )
}

11.【泛型类型 = Min(类类型,泛型参数)】

/* 11.【泛型类型 = Min(类类型,泛型参数)】 */
public class GenericityClass<T> {
    var value = [T]()
    func someFunction(value:T) { }
}
private let genericityPrivate = GenericityClass<SomePrivateClass>() //泛型类型为private
internal let genericityInternal = GenericityClass<SomeInternalClass>() //泛型类型为internal
public let genericityPublic = GenericityClass<SomePublicClass>() //泛型类型为public
//Error:public let genericityInternal = GenericityClass<SomeInternalClass>() //泛型类型为internal

12.【类型别名 <= 原类型】

/* 12.【类型别名 <= 原类型】 */
//包含类型别名的类,遵循【成员<=类】
public class MyClass {
    //声明一个类型别名,类型别名是一个为已存在类型定义的一个可选择的名字
    private typealias privateName1 = SomePrivateClass
    private typealias privateName2 = SomeInternalClass
    private typealias privateName3 = SomePublicClass
    //internal的类型别名可以是internal、public的类型,不可以是private类型
    //Error:-> internal typealias internalName1 = SomePrivateClass
    internal typealias internalName2 = SomeInternalClass
    internal typealias internalName3 = SomePublicClass
    //public的类型别名只能是public的类型
    //Error:-> public typealias publicName1 = SomePrivateClass
    //Error:-> public typealias publicName2 = SomeInternalClass
    public typealias publicName3 = SomePublicClass
    
    private var someProperty = privateName1()
}

有什么问题可以在下方评论区中提出!O(∩_∩)O哈!

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

推荐阅读更多精彩内容