Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Swift have access modifiers?

People also ask

What are access controls in Swift?

Access control restricts access to parts of your code from code in other source files and modules. This feature enables you to hide the implementation details of your code, and to specify a preferred interface through which that code can be accessed and used.

What is open VAR in Swift?

Open vars and functions are open for overriding in other modules. Its the least restrictive access level. It is as good as public access except that something that is public is closed for inheritance in other modules.

What is the default access level in Swift?

internal is the default access level, and makes a declaration visible within the whole module that it's defined in. public reveals a function, type, extension or property outside of its module. open enables a class to be subclassed, and a function or property to be overridden, outside of its module.


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

Swift 4 / Swift 5

As per mentioned in the Swift Documentation - Access Control, Swift has 5 Access Controls:

  • open and public: can be accessed from their module's entities and any module's entities that imports the defining module.

  • internal: can only be accessed from their module's entities. It is the default access level.

  • fileprivate and private: can only be accessed in limited within a limited scope where you define them.



What is the difference between open and public?

open is the same as public in previous versions of Swift, they allow classes from other modules to use and inherit them, i.e: they can be subclassed from other modules. Also, they allow members from other modules to use and override them. The same logic goes for their modules.

public allow classes from other module to use them, but not to inherit them, i.e: they cannot be subclassed from other modules. Also, they allow members from other modules to use them, but NOT to override them. For their modules, they have the same open's logic (they allow classes to use and inherit them; They allow members to use and override them).


What is the difference between fileprivate and private?

fileprivate can be accessed from the their entire files.

private can only be accessed from their single declaration and to extensions of that declaration that are in the same file; For instance:

// Declaring "A" class that has the two types of "private" and "fileprivate":
class A {
    private var aPrivate: String?
    fileprivate var aFileprivate: String?

    func accessMySelf() {
        // this works fine
        self.aPrivate = ""
        self.aFileprivate = ""
    }
}

// Declaring "B" for checking the abiltiy of accessing "A" class:
class B {
    func accessA() {
        // create an instance of "A" class
        let aObject = A()

        // Error! this is NOT accessable...
        aObject.aPrivate = "I CANNOT set a value for it!"

        // this works fine
        aObject.aFileprivate = "I CAN set a value for it!"
    }
}



What are the differences between Swift 3 and Swift 4 Access Control?

As mentioned in the SE-0169 proposal, the only refinement has been added to Swift 4 is that the private access control scope has been expanded to be accessible from extensions of that declaration in the same file; For instance:

struct MyStruct {
    private let myMessage = "Hello World"
}

extension MyStruct {
    func printMyMessage() {
        print(myMessage)
        // In Swift 3, you will get a compile time error:
        // error: 'myMessage' is inaccessible due to 'private' protection level

        // In Swift 4 it should works fine!
    }
}

So, there is no need to declare myMessage as fileprivate to be accessible in the whole file.


When one talks about making a "private method" in Swift or ObjC (or ruby or java or…) those methods aren't really private. There's no actual access control around them. Any language that offers even a little introspection lets developers get to those values from outside the class if they really want to.

So what we're really talking about here is a way to define a public-facing interface that merely presents the functionality we want it to, and "hides" the rest that we consider "private".

The Swift mechanism for declaring interfaces is the protocol, and it can be used for this purpose.

protocol MyClass {
  var publicProperty:Int {get set}
  func publicMethod(foo:String)->String
}

class MyClassImplementation : MyClass {
  var publicProperty:Int = 5
  var privateProperty:Int = 8

  func publicMethod(foo:String)->String{
    return privateMethod(foo)
  }

  func privateMethod(foo:String)->String{
    return "Hello \(foo)"
  }
}

Remember, protocols are first-class types and can be used anyplace a type can. And, when used this way, they only expose their own interfaces, not those of the implementing type.

Thus, as long as you use MyClass instead of MyClassImplementation in your parameter types, etc. it should all just work:

func breakingAndEntering(foo:MyClass)->String{
  return foo.privateMethod()
  //ERROR: 'MyClass' does not have a member named 'privateMethod'
}

There are some cases of direct assignment where you have to be explicit with type instead of relying on Swift to infer it, but that hardly seems a deal breaker:

var myClass:MyClass = MyClassImplementation()

Using protocols this way is semantic, reasonably concise, and to my eyes looks a lot like the Class Extentions we've been using for this purpose in ObjC.


As far as I can tell, there are no keywords 'public', 'private' or 'protected'. This would suggest everything is public.

However Apple may be expecting people to use “protocols” (called interfaces by the rest of the world) and the factory design pattern to hide details of the implementation type.

This is often a good design pattern to use anyway; as it lets you change your implementation class hierarchy, while keeping the logical type system the same.