Swift訪問控制
限制訪問代碼塊,模塊和抽象通過訪問控制來完成。類,結構和枚舉可以根據自己的屬性,方法,初始化函數和下標來通過訪問控制機制進行訪問。常量,變量和函數的協議限制,並允許通過訪問控制來訪問全局和局部變量。應用於屬性,類型及函數的訪問控制可以被稱爲「實體」。
訪問控制模型是基於模塊和源文件的。
模塊定義爲代碼分配一個單獨的單元,並且可以使用import 關鍵字導入。源文件被定義爲一個單一的源代碼文件,模塊可訪問多種類型和函數。
三種不同的訪問級別是由 Swift 語言提供。它們分別是 Public, Internal 和 Private 訪問。
方法級別
定義
Public
啓用實體可以以任何源文件從它們的定義模塊處理,導入已定義模塊到另一個模塊的源文件中。
Internal
從它們定義模塊啓用實體被包含在任何的源文件,但不是在模塊的外部的任何源文件。
Private
限制使用一個實體的自身限定源文件。private訪問扮演的角色是隱藏一個特定代碼功能的實現細節。
語法
public class SomePublicClass {} internal class SomeInternalClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 private func somePrivateFunction() {}
對於函數類型的訪問控制
某些函數可能有參數在函數聲明中但沒有任何返回值。下面的程序聲明 a 和 b 作爲參數傳遞給sum()函數。內部函數本身爲參數a和b的值是通過調用所述通過調用函數 sum(),其值被打印從而不用返回值。爲了使函數的返回類型爲私有,聲明函數使用 private 修飾整體訪問級別。
private func sum(a: Int, b: Int) { let a = a + b let b = a - b
println(a, b) } sum(20, 10) sum(40,10) sum(24,6)
當我們使用 playground 運行上面的程序,得到以下結果
(30, 20)
(50, 40)
(30, 24)
對於枚舉類型的訪問控制
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): println("Student name is: \(studName).") case .Mark(let Mark1, let Mark2, let Mark3): println("Student Marks are: \(Mark1),\(Mark2),\(Mark3).") default: println("Nothing") }
當我們使用 playground 運行上面的程序,得到以下結果
Student Marks are: 98,97,95
枚舉在Swift語言中將自動接收枚舉個體並都具有相同的訪問級別。例如,考慮訪問固定於三個科目枚舉名稱,學生的名字和標記被聲明爲 student 而存在於枚舉類中的成員都屬於字符串數據類型名稱,標記表示爲 mark1, mark2 和 mark3 數據類型爲整數。要訪問無論是學生名稱或標記分數。 現在,如果被執行 Switch case 塊將打印學生姓名,否則它將打印由學生固定的標記。如果這兩個條件都失敗默認塊將被執行。
子類訪問控制
Swift 允許用戶子類,可以在當前訪問上下文存取的任何類。子類不能比其超類有更高的訪問級別。 用戶限制一個公共子類寫入一個內部超類。
public class cricket { private func print() { println("Welcome to Swift Super Class") } } internal class tennis: cricket { override internal func print() { println("Welcome to Swift Sub Class") } } let cricinstance = cricket() cricinstance.print() let tennisinstance = tennis() tennisinstance.print()
當我們使用 playground 運行上面的程序,得到以下結果
Welcome to Swift Super Class
Welcome to Swift Sub Class
常量,變量,屬性和下標訪問控制
Swift 常量,變量或屬性不能被定義比其類型更公開。這是無效一個 public 屬性與 private 類型的寫法。同樣,下標不能超過其索引或返回類型更公開。
當一個常量,變量,屬性或下標使用了一個私有類型,則常量,變量,屬性或下標,也必須標記爲私有:
private var privateInstance = SomePrivateClass()
Getters 和 Setters
getter和setter常量,變量,屬性和標自動接收它們屬於相同的訪問級別的常量,變量,屬性或下標。
class Samplepgm { private var counter: Int = 0{ willSet(newTotal){ println("Total Counter is: \(newTotal)") } didSet{ if counter > oldValue { println("Newly Added Counter \(counter - oldValue)") } } } } let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
當我們使用 playground 運行上面的程序,得到以下結果
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
訪問控制的初始化和默認初始化器
自定義初始化函數可分配的接入級別小於或等於它們初始化的類型。一個必需的初始化必須具有相同的訪問級別,因爲它們和類相同。一個初始化的參數的類型不能比初始化自己的訪問級別更私密(更高)。
聲明每個和初始化每個子類, 「required」 關鍵字需要在init()函數之前定義。
class classA { required init() { var a = 10 println(a) } } class classB: classA { required init() { var b = 30 println(b) } } let res = classA() let print = classB()
當我們使用 playground 運行上面的程序,得到以下結果
10
30
10
默認初始化具有相同的訪問級別,因爲它初始化,除非該類型被定義爲公共類型。 當默認初始化定義爲公共它被認爲是內部的。當用戶需要一個公共類型在另一個模塊中的一個無參數初始化進行初始化,明確提供一個公共的無參數初始化作爲類型定義的一部分。
對於協議的訪問控制
當我們定義一個新的協議,從現有的協議繼承的功能,既有聲明相同的訪問級別以相互繼承屬性。Swift 訪問控制允許用戶定義 「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 print = subClass(no1: 30, no2: 50) println("res is: \(res.no1)") println("res is: \(print.no1)") println("res is: \(print.no2)")
當我們使用 playground 運行上面的程序,得到以下結果
res is: 20
res is: 30
res is: 50
擴展訪問控制
當用戶使用擴展來添加協議的一致性,Swift 不允許用戶爲擴展提供一個明確的訪問級別修飾符。對於在每個協議的擴展,要求實現的默認訪問級別設置自己的協議訪問級別。
對於泛型訪問控制
泛型允許用戶指定最小訪問級別來訪問類型約束其類型參數。
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") println(tos.items) tos.push("Generics") println(tos.items) tos.push("Type Parameters") println(tos.items) tos.push("Naming Type Parameters") println(tos.items) let deletetos = tos.pop()
當我們使用 playground 運行上面的程序,得到以下結果
[Swift]
[Swift, Generics]
[Swift, Generics, Type Parameters]
[Swift, Generics, Type Parameters, Naming Type Parameters]
對於類型別名訪問控制
用戶可以定義類型別名對待不同的訪問控制類型。 相同的訪問級別或不同的訪問級別可以由用戶定義。當類型別名爲 「private」 及其相關成員可以聲明爲 「private,內部 public 類型 」。當類型別名是公共成員不能是別名爲 「internal」 或 「private」 的名稱
定義任何類型別名被視爲用於不同類型的訪問控制的目的。一個類型別名可以具有小於或等於它的一個訪問級別別名的類型的訪問級別。例如,private類型別名可以別名爲 private, internal, 或 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
當我們使用 playground 運行上面的程序,得到以下結果
[Swift]
[Swift, Generics]
[Swift, Generics, Where Clause]
[Swift, Generics, Where Clause]