Search code examples
swift3swift4access-controlaccess-modifiersaccess-levels

Difference between fileprivate and private extension?


Swift 3.0

I know that fileprivate access level modifier limited using of function/property to source file where it was declared and private - limited to lexical scope where was declared. But it seems that this rule not apply for extensions. E.G. this code is valid:

class Foo {
}

fileprivate extension Foo {
    var aa: Int {
        return aaa + 10
    }
}

private extension Foo {
    var aaa: Int {
        return 20
    }
}

Can someone help me figured out difference between them? Thanks.

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.

fileprivate is accessible within same file.


Solution

  • The difference only crops up when we are talking about type members. private will restrict access to other methods within the same type definition, while fileprivate things are accessible by anything that lives in the same .swift file.

    For things that live at the top level (outside of a type definition), private and fileprivate do exactly the same thing. So when you write

    fileprivate extension Foo 
    {
        var aa: Int 
        {
            return aaa + 10
        }
    }
    
    private extension Foo 
    {
        var aaa: Int 
        {
            return 20
        }
    }
    

    You really wrote

    fileprivate extension Foo 
    {
        var aa: Int 
        {
            return aaa + 10
        }
    }
    
    fileprivate extension Foo 
    {
        var aaa: Int 
        {
            return 20
        }
    }
    

    Ultimately, the two extensions on the same protocol get resolved by the compiler into a single extension.

    fileprivate extension Foo 
    {
        var aa: Int 
        {
            return aaa + 10
        }
        var aaa: Int 
        {
            return 20
        }
    }
    

    If you think think having two keywords like this is stupid, some Swift architects agree with you. I believe some style guides recommend you only bother using the public and private access modifiers (as well as the internal modifier, but that one is by default) because, in general, restricting things on a per-file basis, as opposed to a per-module or per-type basis is not particularly useful.

    If you must use the fileprivate modifier, then never use the private modifier outside of a type scope. It’s confusing (since the private in that context “really” means fileprivate) and makes your code harder to read.