Swift-訪問(wèn)控制

【返回目錄】



訪問(wèn)控制(Access Control)

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


  • 訪問(wèn)級(jí)別的使用準(zhǔn)則
    • 變量/常量類(lèi)型 >= 變量/常量
    • 參數(shù)類(lèi)型、返回值類(lèi)型 >= 函數(shù)
    • 父類(lèi) >= 子類(lèi)
    • 父協(xié)議 >= 子協(xié)議
    • 原類(lèi)型 >= typealias
    • 原始值類(lèi)型、關(guān)聯(lián)值類(lèi)型 >= 枚舉類(lèi)型
    • 定義類(lèi)型A時(shí)用到的其他類(lèi)型 >= 類(lèi)型A




元組類(lèi)型訪問(wèn)級(jí)別

  • 元組類(lèi)型訪問(wèn)級(jí)別,是所有成員類(lèi)型最低的那個(gè)
internal struct Dog {}
fileprivate class Person {}


  • Person類(lèi)訪問(wèn)級(jí)別大于等于data1變量級(jí)別
fileprivate var data1: (Dog, Person)


  • Person修飾的級(jí)別大于data2變量(private)
private var data2: (Dog, Person)




范型類(lèi)型訪問(wèn)級(jí)別

  • 范型類(lèi)型的訪問(wèn)級(jí)別是「類(lèi)型的訪問(wèn)級(jí)別」以及「所有范型類(lèi)型參數(shù)的訪問(wèn)級(jí)別」中最低的那個(gè)
internal class Car {}
fileprivate class Dog {}
public class Person<T1, T2> {}

//Person<Car, Dog>()的訪問(wèn)級(jí)別是fileprivate
fileprivate var p = Person<Car, Dog>()




成員、嵌套類(lèi)型

  • 類(lèi)型的訪問(wèn)級(jí)別會(huì)影響成員(屬性、方法、初始化器、下標(biāo))、嵌套類(lèi)型的默認(rèn)訪問(wèn)級(jí)別
  • 一般情況下,類(lèi)型為 private 或 filePrivate,那么成員/嵌套類(lèi)型默認(rèn)也是 private 或 filePrivate
  • 一般情況下,類(lèi)型為 internal 或 public,那么成員/嵌套類(lèi)型默認(rèn)是 internal
public class PublicClass {
    public var p1 = 0 // public
    var p2 = 0 // internal
    fileprivate func fn1() {} //fileprivate
    private func fn2() {}
}

class InternalClass {
    var p = 0  // internal
    fileprivate func fn1() {}
    private func fn2() {}
}

fileprivate class FilePrivatelClass {
    func fn1() {}
    private func fn2() {}
}

private class PrivatelClass {
    func fn1() {} // private
}



  • 示例1:子類(lèi)權(quán)限小于父類(lèi)權(quán)限
private class Person {}
fileprivate class Student: Personal {}

編譯器報(bào)錯(cuò):Cannot find type 'Personal' in scope


  • 示例2:在全局作用域下定義的private等價(jià)于fileprivate
private struct Dog {
    var age: Int = 0
    func run() {}
}

fileprivate struct Person {
    var dog: Dog = Dog()
    mutating func walj() {
        dog.run()
        dog.age = 18
    }
}


  • Dog成員訪問(wèn)級(jí)別最低,在外部無(wú)法使用,引起編譯器報(bào)錯(cuò):
private struct Dog {
    private var age: Int = 0
    private func run() {}
}

fileprivate struct Person {
    var dog: Dog = Dog()
    mutating func walj() {
        dog.run()
        dog.age = 18
    }
}
  • 編譯器報(bào)錯(cuò):'run' is inaccessible due to 'private' protection level
  • 編譯器報(bào)錯(cuò):'age' is inaccessible due to 'private' protection level


成員的重寫(xiě)

  • 字類(lèi)重寫(xiě)成員的訪問(wèn)級(jí)別必須 ≥ 字類(lèi)的訪問(wèn)級(jí)別,或者 ≥ 父類(lèi)被重寫(xiě)成員的訪問(wèn)級(jí)別
  • 父類(lèi)的成員不能被成員作用域外定義的子類(lèi)重寫(xiě)。




Getter Setter

  • getter、setter默認(rèn)自動(dòng)接受它們所屬環(huán)境的訪問(wèn)級(jí)別
  • 可以給setter單獨(dú)設(shè)置一個(gè)比getter更低的訪問(wèn)級(jí)別,用以限制寫(xiě)的權(quán)限。
class Personal {
    //private(set)只讀,不能寫(xiě)入
    private(set) var age = 0
    
    //只讀的計(jì)算屬性
    fileprivate(set) public var  weight: Int {
        set { }
        get { 10 }
    }
    
    //只讀的下標(biāo)
    internal(set) public subscript(index: Int) -> Int {
        set { }
        get { 10 }
    }
}

如果嘗試賦值編譯器報(bào)錯(cuò):Cannot assign to property: 'age' setter is inaccessible


  • fileprivate(set)
//是全局變量,當(dāng)前文件都可以訪問(wèn),但不能改變它。
fileprivate(set) public var number = 10




初始化器

  • 1.如果一個(gè) public 類(lèi)想在另一個(gè)模塊調(diào)用編譯器生成的默認(rèn)無(wú)參初始化器,必須顯示提供 public 的無(wú)參初始化器

  • 2.因?yàn)?public 類(lèi)的默認(rèn)初始化器是 internal 級(jí)別

  • 3.required 初始化器必須跟它所屬類(lèi)擁有相同的訪問(wèn)級(jí)別

  • 4.如果結(jié)構(gòu)體有 private、fileprivate 的存儲(chǔ)實(shí)例屬性,那么它的成員初始化器也是 private、fileprivate
struct MyPoint {
    private var x = 0
    var y = 0
}
//var p = MyPoint(x: 10, y: 20) //成員初始化器
var p2 = MyPoint()


  • 默認(rèn)是 internal




枚舉

  • 不能給 enum 的每個(gè) case 單獨(dú)設(shè)置訪問(wèn)級(jí)別
  • 每個(gè) case 自動(dòng)接受 enum 的訪問(wèn)級(jí)別
  • public enum { } 定義的 case 也是 public
public enum Season {
    case spring
    case summer
    case aotumn
    case winter
}

給case修飾權(quán)限報(bào)錯(cuò):'private' modifier cannot be applied to this declaration




協(xié)議

  • 協(xié)議中定義的要求自動(dòng)接受協(xié)議的訪問(wèn)級(jí)別,不能單獨(dú)設(shè)置訪問(wèn)級(jí)別
    • public協(xié)議定義的要求也是public
  • 協(xié)議實(shí)現(xiàn)的訪問(wèn)級(jí)別必須 >= 類(lèi)型的訪問(wèn)級(jí)別,或者 >= 協(xié)議的訪問(wèn)級(jí)別
public protocol Runnable {
    func run()
}

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




擴(kuò)展

  • 如果有顯式設(shè)置擴(kuò)展的訪問(wèn)級(jí)別,擴(kuò)展添加的成員自動(dòng)接收擴(kuò)展的訪問(wèn)級(jí)別
  • 如果沒(méi)有顯式設(shè)置擴(kuò)展的訪問(wèn)級(jí)別,擴(kuò)展添加的成員的默認(rèn)訪問(wèn)級(jí)別,跟寫(xiě)在類(lèi)型中定義的成員一樣。
class Person {
    func run() {}
}
extension Person { }
class Person { }
private extension Person {
    func run() {}
}


  • 可以單獨(dú)給擴(kuò)展添加的成員設(shè)置訪問(wèn)級(jí)別
extension Person {
    private func run() {}
}


  • 不能給用于遵守協(xié)議的擴(kuò)展顯式設(shè)置擴(kuò)展的訪問(wèn)級(jí)別
fileprivate extension Person: Equatable {
    func test(){}
}

編譯報(bào)錯(cuò):'fileprivate' modifier cannot be used with extensions that declare protocol conformances


  • 在同一文件中的擴(kuò)展,可以寫(xiě)成類(lèi)似多個(gè)部分的類(lèi)型聲明

  • 在原本的聲明中聲明一個(gè)私有成員,可以在同一文件的擴(kuò)展中訪問(wèn)它

  • 在擴(kuò)展中聲明一個(gè)私有成員,可以在同一文件中的其他擴(kuò)展中、原本聲明中訪問(wèn)它

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









【上一篇】:擴(kuò)展
【下一篇】:內(nèi)存管理




最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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