Swift Access Control
Access control can restrict the access level of code in other source files or modules to your code.
You can explicitly set access levels for individual types (classes, structures, enumerations), and also set access levels for properties, functions, initializers, basic types, subscripts, etc. of these types.
Protocols can also be restricted to a certain scope, including global constants, variables, and functions in the protocol.
Access control is based on modules and source files.
A module refers to a Framework or Application built and released as an independent unit. In Swift, one module can use the import keyword to import another module.
A source file is a single source code file, which usually belongs to a module. A source file can contain definitions of multiple classes and functions.
Swift provides four different access levels for entities in code:public、internal、fileprivate、private。
| Access Level | Definition |
|---|---|
| public | Can access any entity in source files within its own module, and others can also access all entities in the source files by importing the module. |
| internal | Can access any entity in source files within its own module, but others cannot access entities in the source files of that module. |
| fileprivate | Private to the file, can only be used in the current source file. |
| private | Can only be accessed within the class; once outside the scope of the class or structure, it cannot be accessed. |
public is the highest access level, and private is the lowest access level.
Syntax
Use the modifiers public, internal, fileprivate, and private to declare the access level of an entity:
Example
Unless otherwise specified, entities use the default access level internal.
Unspecified access level defaults to internal
Function Type Access Control
The access level of a function is determined by 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.
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// 函数实现
}
One of the classes in the function, SomeInternalClass, has an access level of internal, and another, SomePrivateClass, has an access level of private. Therefore, according to the tuple access level principle, the tuple's access level is private (the tuple's access level is the same as the lowest access level among the types in the tuple).
Because the function's return type has a private access level, you must use the private modifier to explicitly declare the function:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// 函数实现
}
Declaring the function as public or internal, or using the default access level internal, is wrong, because if you do so you cannot access the private-level return value.
Enumeration Type Access Control
The access level of members in an enumeration is inherited from the enumeration; you cannot individually declare different access levels for members in the enumeration.
Example
For example, in the following example, the enumeration Student is explicitly declared as public, so its members Name and Mark also have the access level public:
Example
The output of the above program execution is:
学生成绩: 98,97,95
Subclass Access Control
The access level of a subclass must not be higher than that of its superclass. For example, if the superclass has an internal access level, the subclass cannot be declared as public.
Example
The output of the above program execution is:
Superclass
Access Control for Constants, Variables, Properties, and Subscripts
Constants, variables, and properties cannot have a higher access level than their types.
For example, if you define a property with a public access level but its type is private, the compiler will not allow it.
Similarly, a subscript cannot have a higher access level than its index type or return type.
If the defined type of a constant, variable, property, or subscript index is private, then they must explicitly declare their access level as private:
private var privateInstance = SomePrivateClass()
Getter and Setter Access Control
The access levels of Getters and Setters for constants, variables, properties, and subscript indexes are inherited from the access level of the member they belong to.
The access level of a Setter can be lower than the corresponding Getter's access level, allowing you to control the read and write permissions of variables, properties, or subscript indexes.
Example
The access level of counter is fileprivate, so it can be accessed within the file.
The output of the above program execution is:
计数器: 100 新增加数量 100 计数器: 800 新增加数量 700
Initializer and Default Initializer Access Control
Initialization
We can declare access levels for custom initializers, but they must not be higher than the access level of the class they belong to. However, required initializers are an exception; their access level must be the same as the access level of the class they belong to.
Just like function or method parameters, the access levels of initializer parameters cannot be lower than the initializer's access level.
Default Initializer Methods
Swift provides a default no-parameter initializer for structures and classes to provide assignment operations for all their properties, but it does not give specific values.
The access level of a default initializer is the same as the access level of its containing type.
Example
Use the required keyword before the init() method of each subclass to declare access permissions.
Example
The output of the above program execution is:
10 30 10
Protocol Access Control
If you want to explicitly declare an access level for a protocol, note that you must ensure the protocol is only used within the access level scope you declared.
If you define a protocol with a public access level, the required functions that implement the 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.
Example
The output of the above program execution is:
res is: 20 res is: 30 res is: 50
Extension Access Control
You can extend classes, structures, and enumerations when conditions allow. Extension members should have the same access level as members of the original class. For example, if you extend a public type, your newly added members should have the same default internal access level as the original members.
Alternatively, you can explicitly declare the access level of the extension (such as using private extension) to declare a new default access level for all members in the extension. This new default access level can still be overridden by access levels declared by individual members.
Generic Access Control
The access level of a generic type or generic function is the lowest access level among the generic type, the function itself, and the generic type parameters.
Example
The output of the above program execution is:
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "类型参数"] ["Swift", "泛型", "类型参数", "类型参数名"]
Type Aliases
Any type alias you define will be treated as a different type for access control purposes. The access level of a type alias cannot be higher than the access level of the original type.
For example, a private-level type alias can be set for a public, internal, or private type, but a public-level type alias can only be set for a public type, and cannot be set for internal or private types.
Note: This rule also applies when naming aliases for related types to satisfy protocol conformance.
Example
The output of the above program execution is:
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "Where 语句"] ["Swift", "泛型", "Where 语句"]Other Extensions