What is a good example to differentiate between fileprivate and private in Swift3

前端 未结 10 888
醉梦人生
醉梦人生 2020-11-27 10:03

This article has been helpful in understanding the new access specifiers in Swift 3. It also gives some examples of different usages of fileprivate

相关标签:
10条回答
  • 2020-11-27 10:06

    fileprivate is now what private used to be in earlier Swift releases: accessible from the same source file. A declaration marked as private can now only be accessed within the lexical scope it is declared in. So private is more restrictive than fileprivate.

    As of Swift 4, private declarations inside a type are accessible to extensions of the same type if the extension is defined in the same source file.

    Example (all in one source file):

    class A {
        private func foo() {}
        fileprivate func bar() {}
    
        func baz() {
            foo()
            bar()
        }
    }
    
    extension A {
        func test() {
            foo() // Swift 3: error: use of unresolved identifier 'foo'
                  // Swift 4: no error because extension is in same source file
            bar()
        }
    }
    
    let a = A()
    a.foo() // error: 'foo' is inaccessible due to 'private' protection level
    a.bar()
    
    • The private foo method is accessible only within the scope of the class A { ... } definition. It is not even accessible from an extension to the type (in Swift 3, see the second note below for changes in Swift 4).

    • The file-private bar method is accessible from the same source file.

    Notes:

    1. The proposal SE-0159 – Fix Private Access Levels suggested to revert to the Swift 2 semantics in Swift 4. After a lengthy and controversial discussion on the swift-evolution mailing list, the proposal was rejected.

    2. The proposal SE-0169 – Improve Interaction Between private Declarations and Extensions suggests to make private declarations inside a type accessible to extensions of the same type if the extension is defined in the same source file. This proposal was accepted and implemented in Swift 4.

    0 讨论(0)
  • 2020-11-27 10:06

    In the following example, language constructs modified by private and fileprivate seem to behave identically:

    fileprivate func fact(_ n: Int) -> Int {
        if (n == 0) {
            return 1
        } else {
            return n * fact(n - 1)
        }
    }
    
    private func gauss(_ n: Int) -> Int {
        if (n == 0) {
            return 0
        } else {
            return n + gauss(n - 1)
        }
    }
    
    print(fact(0))
    print(fact(5))
    print(fact(3))
    
    print(gauss(10))
    print(gauss(9))
    

    This is according to intuition, I guess. But, is there any exception?

    Kindest regards.

    0 讨论(0)
  • 2020-11-27 10:16

    I just draw a diagram about private, fileprivate, open and public

    Hope it can quickly help you , for text description please refer to Martin R 's answer

    [ Update Swift 4, 5 ]

    0 讨论(0)
  • 2020-11-27 10:18

    This is the explanation for swift 4. For swift 3, the difference is the private. swift 3 private cannot be accessed by its extension, only Class A itself can access.

    After swift 4, fileprivate becomes a bit redundant, because person normally will not define the subclass in the same file. Private should be enough for most cases.

    0 讨论(0)
  • 2020-11-27 10:21

    In Swift 4.0, Private is now accessible in extension but within same file. If you declare/define extension in other file, then your private variable will not be accessible to your extension**

    File Private
    File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
    Syntax: fileprivate <var type> <variable name>
    Example: fileprivate class SomeFilePrivateClass {}


    Private
    Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
    Syntax: private <var type> <variable name>
    Example: private class SomePrivateClass {}


    Here is more detail about all access levels: Swift - Access Levels

    Look at this images:
    File: ViewController.swift
    Here extension and view controller both are in same file, hence private variable testPrivateAccessLevel is accessible in extension

    enter image description here


    File: TestFile.swift
    Here extension and view controller both are in different files, hence private variable testPrivateAccessLevel is not accessible in extension.

    enter image description here

    enter image description here


    Here class ViewController2 is a subclass of ViewController and both are in same file. Here private variable testPrivateAccessLevel is not accessible in Subclass but fileprivate is accessible in subclass.

    enter image description here

    0 讨论(0)
  • 2020-11-27 10:23

    Updated for Swift 5

    Private vs FilePrivate

    For better clarity paste the code snippet in Playground

    class Sum1 {
        let a: Int!
        let b: Int!
        private var result: Int?
        fileprivate var resultt: Int?
    
        init(a : Int, b: Int) {
            self.a = a
            self.b = b
        }
    
        func sum(){
            result = a + b
            print(result as! Int)
        }
    }
    
    let aObj = Sum1.init(a: 10, b: 20)
    aObj.sum()
    aObj.resultt //File Private Accessible as inside same swift file
    aObj.result //Private varaible will not be accessible outside its definition except extensions
    
    extension Sum1{
    
        func testing() {
    
            // Both private and fileprivate accessible in extensions
            print(result)
            print(resultt)
        }
    }
    
    //If SUM2 class is created in same file as Sum1 ---
    class Sum2{
    
        func test(){
    
            let aSum1 = Sum1.init(a: 2, b: 2)
            // Only file private accessible
            aSum1.resultt
    
        }
    }
    

    Note: Outside of Swift file both private and fileprivate are not accessible.

    0 讨论(0)
提交回复
热议问题