Ghostboard pixel

Swift: Access Control

Swift: Access Control

Encapsulation is one of the most important object-oriented design principles: It hides the internal states and functionality of objects.  You can achieve this by using the access control features of Swift.

Why is access control important?

As said before, access control is the most important way to achieve a good encapsulation. If your code is good encapsulated then the manipulation of an object is only possible from the outside through the usage of a clear defined interface. However, only the object itself knows what is happening exactly inside of it. Because of this it is easier to change the implementation details of an object without breaking the rest of your code. Furthermore, the danger of unintentional modifications of the object is very low.

Where can access control be applied?

The Apple’s Book The Swift Programming Language says

You can assign specific access level to individual types (classes, structures, and enumerations), as well to properties, methods, initilizers, and subscripts belonging to those types. Protocols can be restricted to a certain context, as can global constants, variables, and functions.

So in essence this means you can use access control for everything you define except local variables.

Public and private access

Public is the least restrictive access level. Public members can be seen in the whole project and also if they are important within a framework. Private on the other hand is the most restrictive access level: Properties and methods can only be seen in the class where they are defined in. Let’s take a look at an example. We want to develop a class that does some calculations for an integer array.

public class IntegerArrayCalcuation {
    
    private let array: [Int]
    private let sortedArray: [Int]
    
    public init(array:[Int]) {
        self.array = array
        sortedArray = self.array.sort {
            return $0 < $1
        }
    }
    
    public func calculateDigitSum() -> Int {
        var result = 0
        for digit in array {
            result += digit
        }
        return result
    }
    
    public func smallestNumber() -> Int {
        return sortedArray[0]
    }
    
    public func biggestNumber() -> Int {
        return sortedArray.last!
    }

    

First of all, it is a public class. That means it is accessible in the whole project and even if we build a framework, this class will be visible. If the class is public, it is reasonable that the initializer and the interface are public. In this case, we have three methods that are accessible from outside of the class: calculateDigitSum() , smallestNumber()  and biggestNumber(). On the other hand, the arrays we are using are private. So it is not possible that they can be manipulated from outside of the class. Furthermore, if we would have same methods for internal calculations, we would make them private as well.

Default

If you are not providing an access level, a member has default access. That means it is only visible inside the project or the framework it is defined in. For example, if the IntegerArrayCalculation  would have default access, it couldn’t be used if it were imported trough a framework. Furthermore, a non public class is not visible to the test target before Swift 2.0. In Swift 2.0 this is possible by importing the module with the @testable attribute. So if you are working on a single project it is discussible whether  you are using default or public access level. However, you should always use private access level whenever it is possible!

Some rules

There are some important rules regarding the access level of classes and its members:

  • If you are subclassing, the subclass must have the same access level or a more restrictive access level than the original class.
  • If you are overriding a method, the access level must not have a more restrictive access level.
  • The methods and properties of a class must not have a less restrictive access level than the class itself.

[thrive_text_block color=”blue” headline=”Conclusion”]Since a good encapsulation of your code is a key factor of good object-oriented software design, you should think about this topic extensively.[/thrive_text_block]

References

Swift Programming Series (iBook Store)
Image: @ Andrea Danti / shutterstock.com