YouTip LogoYouTip

Swift Access Control

Access control can restrict the access level of your code from code in other source files or modules. You can explicitly set the access level for individual types (classes, structures, enumerations), as well as for the properties, functions, initializers, basic types, and subscript indices of these types. Protocols can also be restricted to a certain scope, including global constants, variables, and functions within the protocol. Access control is based on modules and source files. A module refers to a Framework or Application that is built and published as a standalone unit. In Swift, a module can import another module using the `import` keyword. A source file is a single source code file, which typically belongs to a module. A source file can contain definitions for multiple classes and functions. Swift provides four different access levels for entities in your code: **public, internal, fileprivate, private**. | Access Level | Definition | | --- | --- | | public | Can access any entity in the source files of your own module, and others can also access all entities in the source files by importing the module. | | internal | Can access any entity in the source files of your own module, but others cannot access the entities in the source files of that module. | | fileprivate | Private within the file; can only be used in the current source file. | | private | Can only be accessed within the class; it cannot be accessed outside the scope of this class or structure. | `public` is the highest access level, and `private` is the lowest access level. ### Syntax Declare the access level of an entity using the modifiers `public`, `internal`, `fileprivate`, `private`: ## Instance ```swift public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 fileprivate func someFilePrivateFunction() {} private func somePrivateFunction() {} Unless otherwise specified, entities use the default access level `internal`. ## Unspecified Access Level Defaults to internal ```swift class SomeInternalClass {} let someInternalConstant = 0 * * * ## Function Type Access Permissions The access level of a function must be derived from the access levels of its parameter types and return type. The following example defines a global function named `someFunction` without explicitly declaring its access level. ```swift func someFunction() -> (SomeInternalClass, SomePrivateClass) { // Function implementation } The access level of one class in the function, `SomeInternalClass`, is `internal`, and the other, `SomePrivateClass`, is `private`. Therefore, according to the principle of tuple access levels, the access level of this tuple is `private` (the access level of a tuple is consistent with the lowest access level among its types). Because the access level of the function's return type is `private`, you must use the `private` modifier to explicitly declare the function: ```swift private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // Function implementation } Declaring the function as `public` or `internal`, or using the default access level `internal`, is an error because you would otherwise be unable to access the `private`-level return value. * * * ## Enumeration Type Access Permissions The access level of enumeration members is inherited from the enumeration itself. You cannot separately declare different access levels for individual members within an enumeration. ### Instance For example, in the following example, the enumeration `Student` is explicitly declared as `public`, so its members `Name` and `Mark` also have the `public` access level: ## Instance ```swift public enum Student { case Name(String) case Mark(Int,Int,Int) } var studDetails = Student.Name("Swift") var studMarks = Student.Mark(98,97,95) switch studMarks { case .Name(let studName): print("Student name: (studName).") case .Mark(let Mark1, let Mark2, let Mark3): print("Student marks: (Mark1),(Mark2),(Mark3)") } The output of the above program execution is: ```text Student marks: 98,97,95 * * * ## Subclass Access Permissions The access level of a subclass cannot be higher than that of its superclass. For instance, if the superclass's access level is `internal`, the subclass's access level cannot be declared as `public`. ## Instance ```swift public class SuperClass { fileprivate func show() { print("Superclass") } } internal class SubClass: SuperClass { override internal func show() { print("Subclass") } } let sup = SuperClass() sup.show() let sub = SubClass() sub.show() The output of the above program execution is: ```text Superclass Subclass * * * ## Constant, Variable, Property, and Subscript Access Permissions Constants, variables, and properties cannot have a higher access level than their types. For example, if you define a `public`-level property, but its type is `private`-level, the compiler will not allow it. Similarly, subscripts cannot have a higher access level than their index type or return type. If the defined type of a constant, variable, property, or subscript index is `private`-level, then they must be explicitly declared with the `private` access level: ```swift private var privateInstance = SomePrivateClass() * * * ## Getter and Setter Access Permissions The access levels of Getters and Setters for constants, variables, properties, and subscript indices are inherited from the access level of the member they belong to. The access level of a Setter can be lower than that of its corresponding Getter, which allows you to control the read-write permissions of variables, properties, or subscript indices. ## Instance ```swift class Samplepgm { fileprivate var counter: Int = 0 { willSet(newTotal) { print("Counter: (newTotal)") } didSet { if counter > oldValue { print("Newly added amount (counter - oldValue)") } } } } let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800 The access level of `counter` is `fileprivate`, so it can be accessed within the file. The output of the above program execution is: ```text Counter: 100 Newly added amount 100 Counter: 800 Newly added amount 700 * * * ## Initializer and Default Initializer Access Permissions ### Initialization We can declare an access level for custom initializers, but it cannot be higher than the access level of the class it belongs to. An exception is the required initializer, whose access level must be the same as the class it belongs to. Just like function or method parameters, the access level of an initializer's parameters cannot be lower than the access level of the initializer itself. ### Default Initializer Swift provides a default parameterless initializer for both structures and classes, which is used to provide assignment operations for all their properties, but without giving specific values. The access level of the default initializer is the same as the access level of the type it belongs to. ### Instance Use the `required` keyword before the `init()` method in each subclass to declare access permissions. ## Instance ```swift class classA { required init() { var a = 10 print(a) } } class classB: classA { required init() { var b = 30 print(b) } } let res = classA() let show = classB() The output of the above program execution is: ```text 10 30 10 * * * ## Protocol Access Permissions If you want to explicitly declare an access level for a protocol, you need to note one thing: ensure that the protocol is only used within the scope of the access level you declared. If you define a `public`-level protocol, the required functions provided by the implementing protocol will also have a `public` access level. This is different from other types; for example, for other types with a `public` access level, their members have an `internal` access level. ## Instance ```swift public protocol TcpProtocol { init(no1: Int) } public class MainClass { var no1: Int init(no1: Int) { self.no1 = no1 } } class SubClass: MainClass, TcpProtocol { var no2: Int init(no1: Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) } required override convenience init(no1: Int) { self.init(no1:no1, no2:0) } } let res = MainClass(no1: 20) let show = SubClass(no1: 30, no2: 50) print("res is: (res.no1)") print("res is: (show.no1)") print("res is: (show.no2)") The output of the above program execution is: ```text res is: 20 res is: 30 res is: 50 * * * ## Extension Access Permissions You can extend classes, structures, and enumerations when conditions permit. Extension members should have the same access level as the original class members. For example, if you extend a public type, the new members you add should have the same default `internal` access level as the original members. Alternatively, you
← C 100 ExamplesSwift Generics β†’