Distinction between private and fileprivate top-level classes
There is no difference in your case. The only time that fileprivate
differs from private
is inside a class, struct, or protocol.
In Swift 3, is there a difference between 'private class Foo' and 'fileprivate class Foo' in regards to member variables?
As said in this Q&A – there's no difference in the access levels between a top-level private
and fileprivate
declaration. private
simply means that it's accessible only in the enclosing scope1, and at the top-level – the file is that scope.
Regarding the documentation comment:
If you define a type’s access level as private or file private, the default access level of its members will also be private or file private.
I would say this is incorrect, or at the very least misleading in the case of private
. The scope in which a given type's members are visible is by default the scope that the type declaration itself is visible in (with the exception of access levels higher than internal
).
Therefore the scope in which a private
type's members are accessible is by default the enclosing scope that defines that type. At the top level, that's the file.
It's probably simpler just to say that type members default to being internal
. Being declared in a type with a lower access level than this (such as private
or fileprivate
) just prevents the members from being visible outside of these access levels (as it makes no sense to refer to a given type's member without being able to see the type itself).
1. Note that in Swift 4, as per SE-0169, extensions of a given type that are declared in the same source file as the type have the same access control scope as the scope of the type declaration. Therefore they can access private
members of the type.
Difference between fileprivate and private extension?
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.
What is a good example to differentiate between fileprivate and private in Swift3
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
theclass 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:
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.
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.
Swift: is there any functional difference between private static let (in a class definition) and fileprivate let (no owner)
The functional difference is minor: Your fileprivate
(which could be private
) global is accessible to all types defined within that file, whereas the former is limited to that one particular SomeClass
.
The “private global” arguably requires non-local reasoning (i.e., you might have to scan through the whole file to see which types are there and might have access to it). On the other hand, the “private static property” makes the intent more clear at glance. As a result, many would favor this “private static property” approach.
For what it is worth, there is a hybrid approach:
class SomeClass {
var possibleValues: [String] {
return Self.someValues
}
}
private extension SomeClass {
private static let someValues: [String] = [
"mrah!",
"blah",
"shmah!"
]
}
It keeps the core type definition very clean, but keeps the namespace for the static
constant. Sometimes it is nice to put various subtypes, methods, and statics in extensions within the same file. It can make it easy to grok the code, facilitates code folding, etc.
Swift 3: The difference between Public and Internal access modifiers?
Your diagram is just incorrect.
Public members of A.swift
and B.swift
are available to C.swift
and D.swift
. The only restriction is that classes can't be subclassed (they would need to be open
.
Does Swift have access modifiers?
As of Swift 3.0.1, there are 4 levels of access, described below from the highest (least restrictive) to the lowest (most restrictive).
1. open
and public
Enable an entity to be used outside the defining module (target). You typically use open
or public
access when specifying the public interface to a framework.
However, open
access applies only to classes and class members, and it differs from public
access as follows:
public
classes and class members can only be subclassed and overridden within the defining module (target).open
classes and class members can be subclassed and overridden both within and outside the defining module (target).
// First.framework – A.swift
open class A {}
// First.framework – B.swift
public class B: A {} // ok
// Second.framework – C.swift
import First
internal class C: A {} // ok
// Second.framework – D.swift
import First
internal class D: B {} // error: B cannot be subclassed
2. internal
Enables an entity to be used within the defining module (target). You typically use internal
access when defining an app’s or a framework’s internal structure.
// First.framework – A.swift
internal struct A {}
// First.framework – B.swift
A() // ok
// Second.framework – C.swift
import First
A() // error: A is unavailable
3. fileprivate
Restricts the use of an entity to its defining source file. You typically use fileprivate
access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
// First.framework – A.swift
internal struct A {
fileprivate static let x: Int
}
A.x // ok
// First.framework – B.swift
A.x // error: x is not available
4. private
Restricts the use of an entity to its enclosing declaration. You typically use private
access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
// First.framework – A.swift
internal struct A {
private static let x: Int
internal static func doSomethingWithX() {
x // ok
}
}
A.x // error: x is unavailable
Related Topics
Are the #If Debug Statements Really Needed for Previews in Swiftui to Remove It in a Release Build
How to Import a Swift Function Declared in a Compiled .Swiftmodule into Another Swift File
How to Retrieve Alamofire Response Header for a Request
Store a Closure as a Variable in Swift
Prevent Nsurlsession from Caching Responses
Cast a Swift Struct to Unsafemutablepointer<Void>
Simultaneous Gesture Recognition for Specific Gestures
How to Handle Closure Recursivity
Pointers, Pointer Arithmetic, and Raw Data in Swift
Accessing Mkmapview Elements as Uiviewrepresentable in the Main (Contentview) Swiftui View
What Do "_" and "In" Mean in Swift Programming Language
Writing Swift Dictionary to File
Swift/Uiview/Drawrect - How to Get Drawrect to Update When Required
Exporting Mp4 Through Avassetexportsession Fails
Multiplying Variables and Doubles in Swift
Checking If an Array of Custom Objects Contain a Specific Custom Object
How to Set Top Left and Right Corner Radius with Desired Drop Shadow in Uitabbar