Access Control

Thanks to access modifiers, we can control the acces of the code from other files or modules. In this way, access to the details of the code pieces is restricted.

It is possible to restrict access to methods, properties or init functions which belongs to Class, Struct or Enumeration.

Starting with the least restrictive in Swift:

* Open
* Public
* Internal
* Fileprivate
* Private

we can list as above.

Default access identifier is internal.

Key Words:
Module -> Written as a single application or framework that can be used by other modules with the “import” keyword.
Source File -> Each Swift files used in modules.
Nested Type -> Type that define within a type.

1) Open
Indicates that it is accessible from any file from the same module or another module included. It can also be used as a subclass wherever access is available and its items can be overridden.

2) Public
It has the same features as “open” as access, but it must be in the same module to be subclassed and its items to be overridden.

3) Internal
Defined as default, “internal” allows access from within the same module.

4) Fileprivate
Allows access only from the file in which it was defined.

5) Private
It imposes restrictions on the defined scope, which is the most restrictive specifier.

Note: Before Swift 4, Item is restricted to access from extensions if it is defined as private.

Things to Consider When Setting an Access Identifier

In an entity with more restrictive access identifier, you shouldn’t define an entity with less restrictions. Because, for example, even if there is a public variable in a class that is private, we cannot access the its public variable before access itself.

In functions, the access restrictor is determined as the most restricted of the parameters, return type and its access identifier.

In Enum, cases will have the access identifier of the enum itself and aren’t specified specifically. RawValue and associatedType can be as permissive as the enum itself.

Nested type has a default access identifier depending on the type which its parent. If a nested type is defined in a “private” or “fileprivate” parent, it has access identifier as its parent. However, when it’s parent is internal or more permissive, then nested type’s identifier is internal.

A subclass cannot have an access identifier with fewer constraints than the parent. In other words, if a class has “private” identifier, its subclasses can be as permissive as “private” at most.

An overriden method may be more permissive than it’s implementation in parent. So, a method that is “fileprivate” in a “public” superclass would be “internal” in a “internal” subclass.

public class FirstClass {
    fileprivate func someMethod() {}
}
 
internal class BusinessClass: FirstClass {
    override internal func someMethod() {}
}

An object cannot have a more permissive access identifier than its class. For example, if a class is declared private, an object of itself cannot be public.

private class Tax {
    
}
 
public var tax = Tax()


The code snippet above will give an error like below:

Variable cannot be declared public because its type ‘Tax’ uses a private type.

Access identifiers of getter and setter of constants and variables are automatically determined as their own access identifier. On the other hand, those can be more restrictive if we wish.

struct Tax {
    var income: Double
    private(set) var exactTax: Double
    var ratio: Double  {
        didSet {
            exactTax = (income / 100) * ratio
        }
    }
}

In the above example, ‘income’, ‘exactTax’ and ‘ratio’s access identifier is automatically set as internal as Tax’s access identifier. But then, access identifier of ‘exactTax’s setter is determined as private. From now on, exactTax will not be changed from outside.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s