In the swift language, there are three types of access modifiers, private,internal and public, respectively. At the same time, Swift's control of access rights is not class-based, butfile-based。 The difference is as follows:
The properties or methods modified by the 1,privateprivate access level can only be accessed in the current swift source file. 2,internal (the default access level, internal modifier can be written and writable) the properties or methods that the internal access level modifies are accessible throughout the module where the source code resides. If it is a frame or library code, it is accessible throughout the framework and is not accessible when the framework is referenced by external code. If it is an app code, it is also available throughout the app code and within the entire app.
3,public
Can be used by anyone using ========================================= access control
Access control can limit the level of access to your code in a source file or module, which means you can control which code you can access and which code you can't access. This feature allows us to hide some of the details of the implementation of the feature, and we can clearly specify which parts of the interface we provide to others are available to them, and which are not visible to them.
You can explicitly give classes, structs, enumerations, set access levels, or you can set access levels for attributes, functions, initialization methods, basic types, subscript indexes, and so on. The protocol can also be limited to a certain extent, including global constants, variables, and functions in the Protocol.
While providing different levels of access, Swift does not stipulate that we want to explicitly specify the level of access in the code at all times. In fact, if we are developing our own apps as independent developers, rather than developing some of themFramework, we can completely not explicitly specify the level of access to the code.
Note: For convenience, you can set access levels in your code (attributes, basic types, functions, etc.) in the following sections we call "entities".
Modules and source files
The access control model in Swift is based on the two concepts of module and source files.
the module refers toFrameworktheApp bundleor . In Swift, you can useimportkeywords to introduce your own projects.
In Swift,FramewordkorApp bundleis handled as a module. This is referred to as aFrameworkmodule in Swift If you are trying to implement a common function, or to package the code in order to encapsulate some common methodsFramework. Regardless of whether it is introduced to an app project or something elseFramework, everything inside it (attributes, functions, etc.) belongs to this module.
The source file refers to Swift, whichSwift Fileis the file that writes the SWIFT code, which usually belongs to a module. Typically a source file contains a类, in and including, and so on类函数属性type.
Access level
Swift provides three different levels of access. These access levels are relative to the entities defined in the source file, and are also relative to the modules to which the source files belong.
Public: You can access any entity in the source file in your module or app, and others can access all the entities in the source file that were introduced into the module. Typically,Frameworkyou can set an interface to a level when it is available to anyonepublic.
Internal: You can access any entity in the source file in your module or app, but others cannot access the entity in the source file in the module. Typically, when an interface orFrameworkan internal structure is used, you can set it to ainternallevel.
Private: An entity that can be used only in the current source file, called a private entity. Usingprivatelevels, you can use it as an implementation detail to hide certain features.
Publicis the highest level of access and is the lowest level ofPrivateaccess.
Usage guidelines for access levels
In Swift, the access level has the following usage guidelines: Access level uniformity. For example:
Anpublicaccess-level variable that cannot define its type as ainternalprivatetype. Because a variable can be accessed by anyone, it is not possible to define its type, so there is an error.
The access level of a function cannot be higher than its parameter, the access level of the return type. Because if a function is defined as apublicparameter or a return type is defined asinternalorprivate, a function can be accessed by anyone, but its arguments and return types are not, and an error can occur.
Default Access Level
All entities in the code, if you do not explicitly define their access levels, they default tointernallevels . In most cases, we don't need to explicitly set an entity's access level, because most of the time we're developing an app bundle.
Access levels for single-target applications
When you write a single-target application, all the functionality of the app is for that app, and it doesn't need to be available to other apps or modules, so we don't need to explicitly set the access level to use the default access levelinternal. But if you want, you can also useprivatelevels to hide the implementation details of some features.
Access level of the framework
When you developFramework, you need to define some entities aspubliclevels so that othersFrameworkcan use their functionality properly after they are imported. These are the entities that you define as thepublicFrameworkAPI.
Note:Frameworkthe internal implementation details can still use the defaultinternallevel, or it can be defined as aprivatelevel. Only the entity you want to use as an API defines it as apubliclevel.
Access control syntax
publicinternalprivateto declare the access level of an entity through modifiers, and:
public class SomePublicClass {}internal class SomeInternalClass {}private class SomePrivateClass {}
public var somePublicVariable = 0internal let someInternalConstant = 0private func somePrivateFunction() {}
Unless there is a special description, the entity uses the default access levelinternal, which can be viewed in the section of the default access level . This means that there isSomeInternalClasssomeInternalConstantno explicit use of modifiers to declare access levels, but they have implicit access levelsinternal:
Class SomeInternalClass {}// Implicit access level internalvar someInternalConstant = 0// Implicit access level internal
Custom Types
If you want to specify an explicit level of access for a custom type, then you need to be clear. That's what you want to ensure that the new type of access level matches its actual scope. For example, if the properties, functions, and return values in a class are scoped only to the current source file, then you can declare the class as a class withoutprivatedeclaring it as a classpublicinternal.
The access level of a class can also affect the default access level of class members (properties, functions, initialization methods, and so on). If you declare a class as aprivateclass, then the default access level for all members of that class will also beprivate. If you declare a class aspubliceither ainternalclass (or an ambiguous specified access level, and the defaultinternalaccess level is used), then all members of that class have access levelsinternal.
Note: As mentioned above, thepublicaccess level for all members of a class defaults to the levelinternal, not thepubliclevel. If you want to declare a member as apubliclevel, you must explicitly declare the member with a modifier. The advantage of this is that when you define a public interface API, you can explicitly choose which properties or methods are required to be exposed, which are used internally, and avoid exposing an internally used property method to a common API error.
Public class SomePublicClass {
// the public class shown
Public var somePublicProperty = 0 // public class member displayed
var someInternalProperty = 0 // implicit internal class member
private func somePrivateMethod() {}// displayed private class member
}
class SomeInternalClass { // implicit internal class
var someInternalProperty = 0 // Implicit internal class member
private func somePrivateMethod() {}// The private class member shown
}
private class SomePrivateClass { // The private class shown
var somePrivateProperty = 0 // The implicit private class member
func somePrivateMethod () {} // implicit private class member
}
Tuple type
The access level of a tuple is the most rigorous use of all types of access levels. For example, if you build a tuple that contains two different types of elements, one with an access level of one element and theinternalother as aprivatelevel, the access level for that tuple isprivate. This means that the access level of the tuple follows the lowest level of access in the tuple .
Note: Tuples differ from classes, structs, enumerations, and functions with separate definitions. The access level of a tuple is automatically deduced when it is used, rather than a definite declaration.
function type
The access level of the function needs to be derived from the access level of the function's parameter type, the return type access level. If the access level of a function based on the parameter type and the return type does not conform to the context, then it is necessary to explicitly assert the access level of the function.
The following example defines a global function namedsomeFunction, and does not explicitly declare its access level. You might think that the function should have a default access levelinternal, but that's not the case. In fact, if you do this, the compiler cannot be compiled:
func someFunction() -> (SomeInternalClass, SomePrivateClass) {// function implementation goes here}
As we can see, the return type of this function is a tuple, which contains two custom classes (which can be consulted on a custom type ). The access level of one of the classes is the other access level is, so according to the principle of theinternalprivatetuple access level, the tuple's access level isprivate(the tuple's access level follows its lowest level of access in the tuple).
Because the function returns the access level of the typeprivate, you must useprivatethe modifier to explicitly apply the function:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {// function implementation goes here}
Declaring the function aspublicorinternal, or using the default access level,internalis wrong, because if you use the function as apublicorinternallevel, you cannot get theprivatereturn value of the level.
Enum type
The access level of a member in an enumeration inherits from the enumeration, and you cannot specify an access level for the members in the enumeration.
For example, the enumerationCompassPointis explicitly declared as apubliclevel, then its members, andNorthSouthEast,WestThe access level is alsopublic:
public enum CompassPoint {case Northcase Southcase Eastcase West}
Raw values and associated values
Any original value in the enumeration definition, or the associated value type must have an access level that is at least higher than the access level of the enumeration. For example, you cannotinternaldefine theprivateoriginal value type of a level in an enumeration of access levels.
Nested types
If aprivatenested type is defined in a level type, the nested type automatically has anprivateaccess level. If apublicnested type is defined in a type of orinternallevel, the nested type automatically has aninternalaccess level. If you want to have an access level for a nested typepublic, you need an explicit access level declaration for that nested type.
Sub-class
The access level of the subclass must not be higher than the access level of the parent class. For example, the access level of the parent class isinternalthat the access level of the subclass cannot be declared aspublic.
In addition, you can override any class member (method, property, initialization method, subscript index, and so on) if the subclass is not higher than the parent class access level and follows the scope of each access level (that is, the module or source file).
If we do not have direct access to a property or function in a class, we can inherit the class, making it easier to access the class members of that class. In the following example,Athe access level of the class ispublic, it contains a functionsomeMethod, the access level isprivate. ClassBinherits the classA, and the access level is declared asinternal, but overrides the access-level method in the classBAprivatesomeMethodand re-declares it as ainternallevel. In this way, we can access class members in a class,privateand we can re-assert their access levels for others to use:
public class A {private func someMethod() {}}internal class B: A {override internal func someMethod() {}}
As long as the subclass is not higher than the parent class access level and follows the scope of each access level (that is, the scope of the scope is in the sameprivatesource file,internalunder the same module), we can even access the parent class member in the subclass, using the subclass member. Even if the parent class has a lower access level than the subclass member:
public class A {private func someMethod() {}}internal class B: A {override internal func someMethod() {super.someMethod()}}
Because the parent classAand child classes areBdefined in the same source file, theyBcan be called in the overridden method in the classsomeMethodsuper.someMethod().
constants, variables, attributes, subscripts
Constants, variables, and properties cannot have a higher level of access than their type. For example, you define apubliclevel property, but its type isprivatelevel, which is not allowed by the compiler. Similarly, the subscript cannot have a higher access level than the index type or return type.
If the definition types of constants, variables, attributes, subscript indexes areprivatelevel, they must be explicitly declared access levelprivate:
private var privateInstance = SomePrivateClass()
Getter and setter
The access levels for constants, variables, attributes, subscript indexes,GettersandSettersthe level of accesses inherit from the access level of the members to which they belong.
SetterLevel of access can be lower than the correspondingGetteraccess level, so that you can control read and write permissions for variables, attributes, or subscript indexes.varbefore orsubscriptdefining a scope, you can private(set)internal(set)declare a lower access level by or before the write permission for its door.
Note: This rule applies to properties that are used as storage or as properties for calculations. Even if you do not explicitly declare a property to be stored,GetterSetterSwift is implicitly createdGetterand used toSetterread the property. Useprivate(set)andinternal(set)can change the access level implicitly created by SwiftSetter. The same is true in the computed properties.
The following example defines a struct named, which records theTrackedStringvaluenumber of times a property has been modified:
struct TrackedString {private(set) var numberOfEdits = 0var value: String = "" {didSet {numberOfEdits++}}}
TrackedStringThe struct defines a property that is used to store the namevalue, typeString, and set the initialization value to""(that is, an empty string). The struct also defines another property that is stored with the name of thenumberOfEditstype, which isIntused to recordvaluethe number of times the property has been modified. The implementation of this feature isvalueimplemented by means of a propertydidSet, whichvalueinvokes the method whenever a new value is assigned to itdidSet,numberOfEditsadding one.
Neither the struct norTrackedStringits properties havevalueexplicitly declared access levels, so they all have the default access levelinternal. However, the properties of the struct arenumberOfEditsprivate(set)declared with modifiers, which means that thenumberOfEditsproperty can only be assigned in the source file that defines the struct.numberOfEditsPropertyGetterremains the default access levelinternal, butSetterthe access level isprivate, which means that the property is readable and writable only in the current source file, and it is only a readable property in the module to which the current source file belongs.
If you instantiate aTrackedStringstruct and modify the value of the property several timesvalue, you will seenumberOfEditsthat the value changes as the number of changes:
var stringToEdit = TrackedString()stringToEdit.value = "This string will be tracked."stringToEdit.value += " This edit will increment numberOfEdits."stringToEdit.value += " So will this one."println("The number of edits is /(stringToEdit.numberOfEdits)")// prints "The number of edits is 3"
Although you can instantiate the struct in another source file and get thenumberOfEditsvalue of the property, you cannot assign it to a value. This will tell the user very well that you can use it without knowing its implementation details.
Initialization
We can specify the access level for a custom initialization method, but it must be below or equal to the access level of the class to which it belongs. However, if the initialization method must be used, it must have the same access level as the owning class.
As with a function or method parameter, the access level of the initialization method parameter cannot be lower than the access level of the initialization method.
Default Initialization method
Swift provides a default, parameterless initialization method for structs and classes that provides assignment operations for all their properties, but does not give a specific value. The default initialization method can be used to see default initializers. The access level of the default initialization method is the same as the access level of the owning type.
Note: If a type is declared as apubliclevel, the access level of the default initialization method isinternal. If you want the non-parametric initialization method to be used in other modules, you must provide anpublicaccess-level, parameterless initialization method.
Default member initialization method for structs
If the access level for any of the storage properties in the struct isprivate, then its default member initialization method access level isprivate. However, the access level of the struct's initialization method is stillinternal.
If you want to use the default member initialization method for the struct in other modules, you need to provide apublicdefault member initialization method with access level.
Agreement
If you want to explicitly declare access levels for a protocol, one thing to note is that you want to make sure that the protocol is only used in the scope of the access level you declare.
Each function that must be implemented in the Protocol has the same level of access as the protocol. This ensures that the user of the Protocol can implement the functions it provides.
Note: If you define anpublicaccess level protocol, then the necessary functions provided by the Protocol will also bepublicthe access level. This differs from other types, such aspublicother types of access levels, where the access level of their members isinternal.
Protocol inheritance
If a new protocol is defined, and the Protocol inherits a known protocol, the new protocol has the highest access level and is the same as the access level of the inherited protocol. For example, you cannot define apublicprotocol to inherit ainternalprotocol.
Protocol consistency
Classes can use protocols that are lower than their own access level. For example, you can define apublicclass of classes that can be used in other modules, and it can take ainternallevel of protocol and can only be used in modules that define the protocol.
The access level of a class that employs the protocol follows its own and the lowest access level in the protocol. That is, if a class is apubliclevel, the protocol used is theinternallevel, and the access level for that class is the same when the protocol is adoptedinternal.
If you adopt a protocol, the access level of the method follows the protocol's access level after implementing the method that the protocol must have. For example, a classpublicof classes with ainternallevel of protocol, the way the class implements the protocol is at leastinternal.
Note: As in swift and objective-c, agreement consistency guarantees that a class cannot use the same protocol in a different way in the same program.
Extended
You can extend the classes, structs, and enumerations as the conditions permit. Extended members should have access levels that are consistent with the original class members. For example, if you extend a public type, your new member should have the same default access level as the original memberinternal.
Alternatively, you can explicitly assert that the extended access level (for example, useprivate extension) specifies a new default access level for all members within the extension. This new default access level can still be overridden by the access level specified by individual members.
Extension of the Protocol
If an extension takes a protocol, you cannot use the access level modifier for that extension to declare it. The method that implements the protocol in the extension will follow the access level of the protocol.
Generic type
The access level of a generic type or generic function follows the lowest level of access in the generic type, the function itself, and the generic type parameter.
Type aliases
Any type aliases that you define will be considered different types for access control. The access level of a type alias is less than or equal to this type of access level. For example, aprivatelevel of type aliases can be set to onepublic,internaland,privatebut apuliclevel of type alias can only be set to apubliclevel of type, cannot be set tointernalorprivateclass type.
Note: This rule also applies to naming aliases for related types to satisfy protocol consistency.
Swift Learning note 7--access control