一、Swift的訪問控制
Swift
中的訪問控制模型基于模塊和源文件這兩個概念
模塊:指的是
Framework
或App bundle
册赛。在Swift
中,可以用import
關(guān)鍵字引入自己的工程嚎尤。源文件:指的是
Swift
中的Swift File
苦酱,就是編寫Swift
代碼的文件切威,它通常是屬于某一個模塊喻旷。
Swift提供了三種不同的訪問級別:
-
Public
:【使用public
修飾】【范圍大】
可以訪問當(dāng)前模塊及其他模塊中的任何實(shí)體(通常用于Framework
) -
Internal
:【使用internal
修飾】【范圍中】
可以訪問當(dāng)前模塊中的任何實(shí)體,但是在模塊外無法訪問牢屋,這是所有實(shí)體的默認(rèn)訪問級別(通常在一個單目標(biāo)Application
中不需要自行設(shè)置訪問級別) -
Private
:【使用private
修飾】【范圍小】
只能訪問當(dāng)前源文件中的實(shí)體,用作隱藏某些功能的實(shí)現(xiàn)細(xì)節(jié)
訪問級別從低到高:Private
< Internal
< Public
訪問控制的使用規(guī)則挺多的槽袄,我這里進(jìn)行了概括:
- 【成員(屬性和方法) <= 類】
- 【(常量烙无、變量、屬性遍尺、下標(biāo)腳本) <= 類型】
- 【Setter <= Getter】
- 【required方法 == 類】【默認(rèn)逐一構(gòu)造函數(shù) <= 所有成員】
- 【子類 <= 父類】【子協(xié)議 <= 父協(xié)議】
- 子類重寫父類成員修改訪問范圍
- 【協(xié)議成員 == 協(xié)議】【類 >= 協(xié)議】【協(xié)議實(shí)現(xiàn) >= 協(xié)議要求】
- 【元組 = Min(所有元素類型)】
- 【函數(shù) = Min(參數(shù)類型截酷,返回值類型)】
- 【枚舉成員 == 枚舉】【(原始值,關(guān)聯(lián)值) >= 枚舉】
- 【泛型類型 = Min(類類型,泛型參數(shù))】
- 【類型別名 <= 原類型】
二乾戏、訪問控制使用規(guī)則詳解
1.【成員(屬性和方法) <= 類】
/*
1.【成員(屬性和方法) <= 類】
如果你將類申明為private類迂苛,那么該類的所有成員的默認(rèn)訪問級別也會成為private
如果你將類申明為public或者internal類,那么該類的所有成員默認(rèn)訪問級別是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.【(常量三幻、變量、屬性呐能、下標(biāo)腳本) <= 類型】
/* 2.【(常量念搬、變量、屬性摆出、下標(biāo)腳本) <= 自己類型】 */
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權(quán)限設(shè)置為private */
/*
這個規(guī)定適用于用作存儲的屬性或用作計(jì)算的屬性。
即使你不明確的申明存儲屬性的Getter象踊、Setter温亲,
Swift也會隱式的為其創(chuàng)建Getter和Setter棚壁,用于對該屬性進(jìn)行讀取操作。
*/
public class SetterPrivateClass {//該類可以在任何模塊中使用
private(set) var value = 0 //設(shè)置存儲屬性的setter為private
//設(shè)置計(jì)算屬性的setter屬性為private
private(set) var setPrivateProperty:Int {
set{//此時setter為private铸豁,也就是只能在本文件中使用灌曙,其他文件無法使用
value = newValue + 1
}
get{//getter默認(rèn)為internal
return value + 1
}
}
}
4.【required方法 == 類】【默認(rèn)逐一構(gòu)造函數(shù) <= 所有成員】
/* 4.【required修飾的方法 == 類】,(結(jié)構(gòu)體)【默認(rèn)逐一構(gòu)造函數(shù) <= 所有成員】 */
protocol RequiredTestProtocol {
//初始化構(gòu)造器要求
init(aprot: Int)
}
public class RequiredTestClass: RequiredTestProtocol {
var aprot: Int //默認(rèn)為internal
//實(shí)現(xiàn)協(xié)議的初始化要求時节芥,必須使用required關(guān)鍵字確保子類必須也得實(shí)現(xiàn)這個構(gòu)造器
public required init(aprot: Int) {//此時必須設(shè)置為public在刺,因?yàn)槟J(rèn)是internal的
self.aprot = aprot
}
}
//該結(jié)構(gòu)體的默認(rèn)逐一構(gòu)造方法為private,但默認(rèn)構(gòu)造方法還是internal
public struct StructInitTest{
private var somePrivateProperty = 0
internal var someInternalProperty = 0
public var somePublicProperty = 0
}
5.【子類 <= 父類】【子協(xié)議 <= 父協(xié)議】
/* 5.【子類 <= 父類】头镊,【子協(xié)議 <= 父協(xié)議】 */
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.不違反前面規(guī)則颖杏,子類可以通過重寫父類方法來修改訪問權(quán)限范圍 */
public class OverrideSuperClass {
private func someMethod() {}
}
internal class OverrideSubClass: OverrideSuperClass {
override internal func someMethod() {
super.someMethod()//子類和父類在同一個源文件中,所以可以訪問super的someMethod()方法
}
}
7.【協(xié)議成員 == 協(xié)議】【類 >= 協(xié)議】【協(xié)議實(shí)現(xiàn) >= 協(xié)議要求】
/* 7.【協(xié)議所有必須實(shí)現(xiàn)的成員 == 協(xié)議】坛芽,【類 >= 協(xié)議】留储,【協(xié)議實(shí)現(xiàn) >= 協(xié)議要求】 */
internal protocol InternalProtocol {
//協(xié)議成員不可以添加訪問控制關(guān)鍵字,默認(rèn)等于協(xié)議的訪問權(quán)限范圍
var someProperty:Int { get set }
func someMethod()
}
//類必須大于或等于要遵循的協(xié)議
public class ProtocolTestClass:InternalProtocol {
//Error:-> private var someProperty = 0 //協(xié)議實(shí)現(xiàn)必須大于或等于協(xié)議要求
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.【函數(shù) = Min(參數(shù)類型活喊,返回值類型)】
/* 9.【函數(shù) = Min(參數(shù)類型丐膝,返回值類型)】 */
private func someFunction(value:SomeInternalClass) -> SomePrivateClass {
//函數(shù)體
return SomePrivateClass()
}
10.【枚舉成員 == 枚舉】【(原始值,關(guān)聯(lián)值) >= 枚舉】
/* 10.【枚舉成員 == 枚舉】,枚舉成員沒法單獨(dú)設(shè)置訪問級別钾菊,【(原始值,關(guān)聯(lián)值) >= 枚舉】 */
private enum PrivateEnum {
case PrivateEnumCase( SomePrivateClass )
case InternalEnumCase( SomeInternalClass )
case PublicEnumCase( SomePublicClass )
}
internal enum InternalEnum {
//Error:-> case PrivateEnumCase( SomePrivateClass ) //關(guān)聯(lián)值必須大于枚舉
case InternalEnumCase( SomeInternalClass )
case PublicEnumCase( SomePublicClass )
}
11.【泛型類型 = Min(類類型帅矗,泛型參數(shù))】
/* 11.【泛型類型 = Min(類類型,泛型參數(shù))】 */
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()
}