iOS學習筆記49 Swift(九)訪問控制

執著丶執念發表於2018-06-02

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哈!

相關文章