18-訪問控制

訪問控制(Access Control)

在訪問權(quán)限控制這塊,Swift提供了5個不同的訪問級別(以下是從高到低排列, 實體指被訪問級別修飾的內(nèi)容)
  • open:允許在定義實體的模塊、其他模塊中訪問,允許其他模塊進行繼承、重寫(open只能用在類、類成員上)
  • public:允許在定義實體的模塊、其他模塊中訪問,不允許其他模塊進行繼承、重寫
  • internal:只允許在定義實體的模塊中訪問,不允許在其他模塊中訪問
  • fileprivate:只允許在定義實體的源文件中訪問
  • private:只允許在定義實體的封閉聲明中訪問
  • 絕大部分實體默認都是internal 級別

訪問級別的使用準則

一個實體不可以被更低訪問級別的實體定義,比如
  • 變量\常量類型≥ 變量\常量
  • 參數(shù)類型、返回值類型≥ 函數(shù)
  • 父類≥ 子類
  • 父協(xié)議≥ 子協(xié)議
  • 原類型≥ typealias
  • 原始值類型、關(guān)聯(lián)值類型≥ 枚舉類型
  • 定義類型A時用到的其他類型≥ 類型A
  • ......

元組類型

  • 元組類型的訪問級別是所有成員類型最低的那個
internal struct Dog {}
fileprivate class Person {}

// (Dog, Person)的訪問級別是fileprivate
fileprivate var data1: (Dog, Person)
private var data2: (Dog, Person)

泛型類型

  • 泛型類型的訪問級別是類型的訪問級別以及所有泛型類型參數(shù)的訪問級別中最低的那個
internal class Car {}
fileprivate class Dog {}
public class Person<T1, T2> {}

// Person<Car, Dog>的訪問級別是fileprivate
fileprivate var p = Person<Car, Dog>()

成員、嵌套類型

  • 類型的訪問級別會影響成員(屬性、方法、初始化器、下標)、嵌套類型的默認訪問級別
  • 一般情況下,類型為private或fileprivate,那么成員\嵌套類型默認也是private或fileprivate
  • 一般情況下,類型為internal或public,那么成員\嵌套類型默認是internal
public class PublicClass {
    public var p1 = 0 // public
    var p2 = 0 // internal
    fileprivate func f1() {} // fileprivate
    private func f2() {} // private
}
class InternalClass { // internal
    var p = 0 // internal
    fileprivate func f1() {} // fileprivate
    private func f2() {} // private
}
fileprivate class FilePrivateClass { // fileprivate
    func f1() {} // fileprivate
    private func f2() {} // private
}
private class PrivateClass { // private
    func f() {} // private
}

成員的重寫

  • 子類重寫成員的訪問級別必須≥ 子類的訪問級別,或者≥ 父類被重寫成員的訪問級別
  • 父類的成員不能被成員作用域外定義的子類重寫
public class Person {
    private var age: Int = 0
}
public class Student : Person {
    override var age: Int {
        set {}
        get {10}
    }
}
public class Person {
    private var age: Int = 0
    public class Student : Person {
        override var age: Int {
            set {}
            get {10}
        }
    }
}

下面代碼能否編譯通過?

private class Person {}
fileprivate class Student : Person {}
private struct Dog {
    var age: Int = 0
    func run() {}
}
fileprivate struct Person {
    var dog: Dog = Dog()
    mutating func walk() {
        dog.run()
        dog.age = 1
    }
}
private struct Dog {
    private var age: Int = 0
    private func run() {}
}
fileprivate struct Person {
    var dog: Dog = Dog()
    mutating func walk() {
        dog.run()
        dog.age = 1
    }
}
  • 直接在全局作用域下定義的private等價于fileprivate

getter、setter

  • getter、setter默認自動接收它們所屬環(huán)境的訪問級別
  • 可以給setter單獨設(shè)置一個比getter更低的訪問級別,用以限制寫的權(quán)限
fileprivate(set) public var num = 10
class Person {
    private(set) var age = 0
    fileprivate(set) public var weight: Int {
        set {}
        get { 10 }
    }
    internal(set) public subscript(index: Int) -> Int {
        set {}
        get { index }
    }
}

初始化器

  • 如果一個public類想在另一個模塊調(diào)用編譯生成的默認無參初始化器,必須顯式提供public的無參初始化器
    因為public類的默認初始化器是internal級別

  • required初始化器≥ 它的默認訪問級別

  • 如果結(jié)構(gòu)體有private\fileprivate的存儲實例屬性,那么它的成員初始化器也是private\fileprivate
    否則默認就是internal

枚舉類型的case

  • 不能給enum的每個case單獨設(shè)置訪問級別

  • 每個case自動接收enum的訪問級別
    public enum定義的case也是public

協(xié)議

  • 協(xié)議中定義的要求自動接收協(xié)議的訪問級別,不能單獨設(shè)置訪問級別
    public協(xié)議定義的要求也是public

  • 協(xié)議實現(xiàn)的訪問級別必須≥ 類型的訪問級別,或者≥ 協(xié)議的訪問級別

  • 下面代碼能編譯通過么?

public protocol Runnable {
    func run()
}
public class Person : Runnable {
    func run() {}
}

擴展

  • 如果有顯式設(shè)置擴展的訪問級別,擴展添加的成員自動接收擴展的訪問級別

  • 如果沒有顯式設(shè)置擴展的訪問級別,擴展添加的成員的默認訪問級別,跟直接在類型中定義的成員一樣

  • 可以單獨給擴展添加的成員設(shè)置訪問級別

  • 不能給用于遵守協(xié)議的擴展顯式設(shè)置擴展的訪問級別

擴展

  • 在同一文件中的擴展,可以寫成類似多個部分的類型聲明
    在原本的聲明中聲明一個私有成員,可以在同一文件的擴展中訪問它
    在擴展中聲明一個私有成員,可以在同一文件的其他擴展中、原本聲明中訪問它
public class Person {
    private func run0() {}
    private func eat0() {
        run1()
    }
}
extension Person {
    private func run1() {}
    private func eat1() {
        run0()
    }
}
extension Person {
    private func eat2() {
        run1()
    }
}

將方法賦值給var\let

  • 方法也可以像函數(shù)那樣,賦值給一個let或者var
struct Person {
    var age: Int
    func run(_ v: Int) { print("func run", age, v) }
    static func run(_ v: Int) { print("static func run", v) }
}

let fn1 = Person.run
fn1(10) // static func run 10

let fn2: (Int) -> () = Person.run
fn2(20) // static func run 20

let fn3: (Person) -> ((Int) -> ()) = Person.run
fn3(Person(age: 18))(30) // func run 18 30
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在訪問控制這塊,Swift提供了五個不同的訪問級別(以下是從高到低排列,實體指被訪問級別修飾的內(nèi)容) open :...
    西風(fēng)那個吹呀吹閱讀 1,421評論 0 2
  • 訪問控制 在訪問權(quán)限控制這塊,Swift提供了5個不同的訪問級別,以下是從高到低的敘述,其中實體是指被訪問級別修飾...
    YanZi_33閱讀 488評論 0 0
  • 中文文檔 一、模塊和源文件 Swift 中的訪問控制模型基于模塊和源文件這兩個概念。 模塊指的是獨立的代碼單元,框...
    伯wen閱讀 361評論 0 0
  • 一、訪問控制(Access Control) Swift提供了5個不同的訪問級別(以下是從高到底排列,實體指被訪問...
    alfei13閱讀 404評論 0 0
  • 訪問控制 可以限定其它源文件或模塊中的代碼對你的代碼的訪問級別。這個特性可以讓我們隱藏代碼的一些實現(xiàn)細節(jié),并且可以...
    答案MK閱讀 346評論 0 0

友情鏈接更多精彩內(nèi)容