Kawalan akses pantas


Kawalan akses boleh mengehadkan tahap akses kod dalam fail sumber atau modul lain kepada kod anda.

Anda boleh menetapkan tahap akses secara eksplisit untuk jenis individu (kelas, struktur, penghitungan), atau untuk sifat, fungsi, kaedah permulaan, jenis asas, indeks subskrip, dll. jenis ini.

Protokol juga boleh dihadkan kepada skop tertentu, termasuk pemalar global, pembolehubah dan fungsi dalam protokol.

Kawalan akses adalah berdasarkan modul dan fail sumber.

Modul merujuk kepada Rangka Kerja atau Aplikasi yang dibina dan diterbitkan sebagai unit bebas. Dalam Swift, modul boleh mengimport modul lain menggunakan kata kunci import.

Fail sumber ialah fail kod sumber tunggal, yang biasanya dimiliki oleh modul Fail sumber boleh mengandungi takrifan berbilang kelas dan fungsi.

Swift menyediakan tiga tahap akses berbeza untuk entiti dalam kod: awam, dalaman dan peribadi.

访问级别定义
Public可以访问自己模块中源文件里的任何实体,别人也可以通过引入该模块来访问源文件里的所有实体。
Internal:可以访问自己模块中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。
Private只能在当前源文件中使用的实体,称为私有实体。

Awam ialah tahap akses tertinggi, dan peribadi ialah tahap akses terendah.

Sintaks

Isytihar tahap akses entiti melalui pengubahsuai awam, dalaman dan peribadi:

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

Melainkan dinyatakan sebaliknya, entiti menggunakan tahap akses lalai dalaman .


Kebenaran akses jenis fungsi

Tahap akses fungsi perlu diperoleh berdasarkan tahap akses jenis parameter dan jenis pemulangan fungsi.

Contoh berikut mentakrifkan fungsi global bernama someFunction dan tidak mengisytiharkan tahap aksesnya secara eksplisit.

func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 函数实现
}

Tahap akses salah satu kelas dalam fungsi, SomeInternalClass, adalah dalaman dan tahap akses yang lain, SomePrivateClass, adalah peribadi. Jadi mengikut prinsip tahap akses tuple, tahap akses tuple ini adalah peribadi.

Oleh kerana tahap akses bagi jenis pulangan fungsi adalah peribadi, anda mesti menggunakan pengubah suai peribadi untuk mengisytiharkan fungsi secara eksplisit:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 函数实现
}

Isytihar fungsi sebagai awam atau dalaman, atau gunakan tahap akses lalai Salah.


Kebenaran akses jenis enumerasi

Tahap akses ahli dalam penghitungan diwarisi daripada penghitungan Anda tidak boleh mengisytiharkan tahap akses yang berbeza secara individu untuk ahli dalam penghitungan.

Instance

Contohnya, dalam contoh berikut, penghitungan Pelajar secara eksplisit diisytiharkan sebagai peringkat awam, kemudian tahap akses ahlinya Nama dan Tanda juga terbuka:

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)")
}

Output pelaksanaan program di atas ialah:

学生成绩: 98,97,95

Kebenaran akses subkelas

Tahap akses subkelas mestilah tidak lebih tinggi daripada tahap akses kelas induk. Sebagai contoh, jika tahap akses kelas induk adalah dalaman, tahap akses subkelas tidak boleh diisytiharkan sebagai awam.

public class SuperClass {
    private func show() {
        print("超类")
    }
}

// 访问级别不能低于超类 internal > public
internal class SubClass: SuperClass  {
    override internal func show() {
        print("子类")
    }
}

let sup = SuperClass()
sup.show()

let sub = SubClass()
sub.show()

Hasil keluaran pelaksanaan program di atas ialah:

超类
子类

Malar, pembolehubah, atribut, hak akses subskrip

Malar, pembolehubah, atribut tidak boleh mempunyai lebih daripada jenis tahap akses yang lebih tinggi.

Sebagai contoh, anda mentakrifkan atribut peringkat awam, tetapi jenisnya adalah peringkat peribadi, yang tidak dibenarkan oleh pengkompil.

Begitu juga, subskrip tidak boleh mempunyai tahap akses yang lebih tinggi daripada jenis indeks atau jenis pulangan.

Jika jenis definisi pemalar, pembolehubah, sifat dan indeks subskrip ialah peringkat peribadi, maka mereka mesti mengisytiharkan secara eksplisit bahawa tahap akses adalah peribadi:

private var privateInstance = SomePrivateClass()

Akses Getter dan Setter Kebenaran

Tahap capaian pengambil dan penetap pemalar, pembolehubah, sifat dan indeks subskrip diwarisi daripada tahap akses ahli yang menjadi milik mereka.

Tahap akses Setter boleh lebih rendah daripada tahap akses Getter yang sepadan, supaya anda boleh mengawal kebenaran baca dan tulis pembolehubah, sifat atau indeks subskrip.

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

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Output pelaksanaan program di atas ialah:

计数器: 100
新增加数量 100
计数器: 800
新增加数量 700

Kebenaran akses pembina dan pembina lalai

Inisialisasi

Kami boleh menyesuaikan Inisialisasi kaedah mengisytiharkan tahap akses, tetapi ia tidak boleh lebih tinggi daripada tahap akses kelas yang dimilikinya. Pengecualian diperlukan pembina, yang tahap aksesnya mestilah sama dengan kelas yang dimilikinya.

Seperti parameter fungsi atau kaedah, tahap capaian parameter kaedah permulaan tidak boleh lebih rendah daripada tahap capaian kaedah permulaan.

Kaedah permulaan lalai

Swift menyediakan kaedah permulaan tanpa parameter lalai untuk struktur dan kelas, yang digunakan untuk menyediakan operasi tugasan untuk semua sifatnya, tetapi tidak memberikan nilai khusus.

Tahap akses kaedah permulaan lalai adalah sama dengan tahap akses jenis yang dimilikinya.

Instance

mengisytiharkan kebenaran akses menggunakan kata kunci yang diperlukan sebelum kaedah init() setiap subkelas.


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()

Hasil output pelaksanaan program di atas ialah:

10
30
10

Hak akses protokol

Jika anda ingin mengisytiharkan secara eksplisit protokol Tahap akses, maka satu perkara yang perlu diberi perhatian ialah anda perlu memastikan bahawa protokol hanya digunakan dalam skop tahap akses yang anda isytiharkan.

Jika anda menentukan protokol dengan tahap akses awam, maka fungsi yang diperlukan yang disediakan oleh protokol juga akan mempunyai tahap akses awam. Ini berbeza daripada jenis lain, seperti jenis lain dengan tahap akses awam, yang ahlinya mempunyai tahap akses dalaman.

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)")

Output pelaksanaan program di atas ialah:

res is: 20
res is: 30
res is: 50

Hak akses lanjutan

Anda boleh melakukan operasi pada kelas, struktur dan penghitungan apabila keadaan membenarkan. Sambungan. Ahli sambungan harus mempunyai tahap akses yang sama seperti ahli kelas asal. Contohnya, jika anda melanjutkan jenis awam, ahli baharu yang anda tambahkan harus mempunyai tahap akses dalaman lalai yang sama seperti ahli asal.


Sebagai alternatif, anda boleh mengisytiharkan secara eksplisit tahap akses sambungan (seperti menggunakan sambungan peribadi) untuk mengisytiharkan tahap akses lalai baharu untuk semua ahli dalam sambungan. Tahap akses lalai baharu ini masih boleh ditindih oleh tahap akses yang diisytiharkan oleh ahli individu.


Hak akses generik

Tahap akses bagi jenis generik atau fungsi generik ialah tahap akses paling rendah antara jenis generik, fungsi itu sendiri dan parameter jenis generik.

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()

Hasil keluaran pelaksanaan program di atas ialah:

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

Taip alias

Sebarang jenis alias yang anda tentukan akan dianggap sebagai jenis yang berbeza untuk kawalan akses mudah. Tahap akses jenis alias tidak boleh lebih tinggi daripada tahap akses jenis asal.

Sebagai contoh, alias jenis peringkat peribadi boleh ditetapkan kepada jenis awam, dalaman atau peribadi, tetapi alias jenis peringkat awam hanya boleh ditetapkan kepada jenis peringkat awam, bukan kepada Dalaman atau jenis peringkat swasta.

Nota: Peraturan ini juga terpakai pada jenis yang berkaitan dengan pengalian untuk pematuhan protokol.

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)

Hasil output pelaksanaan program di atas ialah:

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