Swift4 中訪問控制 private和fileprivate的區(qū)別

一、前言

相信有一些初學Swift的開發(fā)者,對private和fileprivate這兩個訪問控制關(guān)鍵字的使用會有些迷糊,So,今天咱們就來捋一捋。

Swift 中由低至高提供了 private,fileprivate,internal,public 和 open 五種訪問控制的權(quán)限。默認的 internal 在絕大部分時候是適用的,另外由于它是 Swift 中的默認的控制級,因此它也是最為方便的。

對于一個嚴格的項目來說,精確的最小化訪問控制級別對于代碼的維護來說還是相當重要的。我們想讓同一 module (或者說是 target) 中的其他代碼訪問的話,保持默認的 internal 就可以了。如果我們在為其他開發(fā)者開發(fā)庫的話,可能會希望用一些 public 甚至 open,因為在 target 外只能調(diào)用到 public 和 open 的代碼。public 和 open 的區(qū)別在于,只有被 open 標記的內(nèi)容才能在別的框架中被繼承或者重寫。因此,如果你只希望框架的用戶使用某個類型和方法,而不希望他們繼承或者重寫的話,應該將其限定為 public 而非 open。

二、進入主題: private和fileprivate的區(qū)別

Swift3及之前的區(qū)別可以看這里 本篇文章只介紹Swift4

1. private 和 fileprivate 修飾屬性

//ViewController.swift
class Person: NSObject {

    fileprivate var name:String = "man"
    
    private var age:Int = 1
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let p = Person()
        print(p.name)
        
        //編譯器不會提示age屬性 如果強行寫p.age
        //會報錯'age' is inaccessible due to 'private' protection level
        //print(p.age)
    }
}
log:  man
      在swift4.0中 fileprivate修飾的屬性,能在當前文件內(nèi)訪問到,不管是否在本類的作用域;
private 只能在本類的作用域且在當前文件內(nèi)能訪問
//ViewController.swift
extension Person {
    
    func printAge()  {
        print(self.age)
        //在 當前文件的 extension 中,調(diào)用private 修飾的屬性沒問題
    }
    
    func prinName()  {
      //在 當前文件的 extension 中,調(diào)用fileprivate 修飾的屬性沒問題
        print(self.name)
    }
}

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let p = Person()        
        p.printAge()
        p.prinName()
    }

extension中需要用到類的屬性時,只要保證實在同一個文件內(nèi),無論是用privatefileprivate修飾,都是可以被正常訪問的。

2、private 和 fileprivate 修飾方法時

//ViewController.swift
class Person: NSObject {
    fileprivate var name:String = "man"
    
    private var age:Int = 1
    
    fileprivate func printNameAndAge(){
        print("name:\(name) age:\(age)")
    }
    
    private func setNameAndAge(name:String,age:Int){
        //xxx
    }
}

override func viewDidLoad() {
        super.viewDidLoad()
        let p = Person()
        p.printNameAndAge()
        
        //用private修飾的方法不能夠被調(diào)用到
        //'setNameAndAge' is inaccessible due to 'private' protection level
       // p.setNameAndAge("superMan",100)
    }

3.子類是否能使用到private和fileprivate修飾的代碼

3.1在當前文件內(nèi)新加一個Peson的子類

//ViewController.swift 跟父類Person在同一個文件內(nèi)

class Student: Person {
    //依然可訪問到父類中 fileprivate 修飾的方法或?qū)傩?    func test() {
        print("來自Student: \(name) ")
        //print("來自Student: \(age) ") //此時age也是不可訪問的
        
        printNameAndAge() //fileprivate 可正常調(diào)用
        
        //setNameAndAge("daming",13) //private無法調(diào)用
    }
}

3.2在不同文件內(nèi)新加一個Peson的子類


//Teacher.swift
class Teacher: Person {
    func testPrint() {
        //可以訪問extension 中的方法,沒加修飾默認為 internal
        prinName();
        printAge();
        
        //此時 private和fileprivate 修飾的屬性或方法都無法訪問到
        //printNameAndAge()
        //setNameAndAge(name: "SuperMan", age: 100)
        
        // let a =  self.age
        //let b =  self.name
    }
    
    //但不可以被重寫
    //Declarations from extensions cannot be overridden yet
//    override func prinName() {
//        print("子類重寫 prinName")
//    }
//    override func printAge() {
//        print("子類重寫 printAge")
//    }
}

在Swift4中,如果子類跟父類不再同一個文件下是不能夠使用fileprivate修飾的方法或?qū)傩缘?;且private修飾的方法和屬性無論是否跟父類在同一個文件文件內(nèi),都無法使用。

三、總結(jié)

 private 表示代碼只能在當前作用域或者同一文件中同一類型的作用域中被使用,
 fileprivate 表示代碼可以在當前文件中被訪問,而不做類型限定。

再過幾天就是元旦了,祝大家元旦快樂啦~覺得寫得還可以,就點個贊吧??


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

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