English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Access control can limit the access level of code in other source files or modules to your code.
You can explicitly set the access level for a single type (class, structure, enumeration), as well as for properties, functions, initialization methods, basic types, and index subscripts of these types.
Protocols can also be limited to certain scopes of use, 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 built and released as an independent unit. In Swift, a 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 multiple class and function definitions.
Swift provides four different access levels for entities in code: public, internal, fileprivate, and private.
Access Level | Definition |
---|---|
public | Can access any entity in the source files of its own module, and others can also access all entities in the source files of the module by importing the module. |
internal | Can access any entity in the source files of its own module, but others cannot access the entities in the source files of the module. |
fileprivate | Private within the file, accessible only within the current source file. |
private | Accessible only within the class, and cannot be accessed outside the scope of the class or structure. |
public est le niveau d'accès le plus élevé, privé est le niveau d'accès le plus bas.
Déclarer le niveau d'accès des entités à l'aide des modificateurs public, internal, fileprivate, privé :
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() {}
À moins d'être spécifié autrement, les entités utilisent le niveau d'accès par défaut internal.
class SomeInternalClass {} // Le niveau d'accès est internal let someInternalConstant = 0 // Le niveau d'accès est internal
Le niveau d'accès de la fonction doit être déterminé en fonction du type de paramètre et du type de retour de la fonction.
L'exemple suivant définit une fonction globale nommée someFunction et ne déclare pas explicitement son niveau d'accès.
func someFunction() ->(SomeInternalClass, SomePrivateClass) { // Implémentation de la fonction {}
L'un des classes SomeInternalClass dans la fonction a un niveau d'accès internal, et l'autre SomePrivateClass a un niveau d'accès privé. Donc selon le principe d'accès des tuples, le niveau d'accès du tuple est privé (le niveau d'accès du tuple est le même que le type d'accès le plus bas du tuple).
Comme le type de retour de la fonction est de niveau privé, vous devez utiliser le modificateur privé pour déclarer explicitement la fonction :
private func someFunction() ->(SomeInternalClass, SomePrivateClass) { // Implémentation de la fonction {}
Déclarer la fonction en tant que public ou internal, ou utiliser le niveau d'accès par défaut internal est incorrect, car dans ce cas, vous ne pourrez pas accéder aux valeurs de retour de niveau privé.
Le niveau d'accès des membres de l'enumée est hérité de l'enumée, vous ne pouvez pas déclarer des niveaux d'accès différents pour les membres de l'enumée.
Par exemple, dans l'exemple suivant, l'enum Student est explicitement déclaré au niveau public, donc les niveaux d'accès des membres Name, Mark sont également public:
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("Nom de l'étudiant: (studName)." case .Mark(let Mark1, let Mark2, let Mark3) print("Notes des étudiants: (Mark1),(Mark2),(Mark3) {}
以上程序执行输出结果为:
Notes des étudiants: 98,97,95
Le niveau d'accès de la sous-classe ne peut pas être supérieur à celui de la classe mère. Par exemple, si le niveau d'accès de la classe mère est internal, le niveau d'accès de la sous-classe ne peut pas être déclaré en tant que public.
public class SuperClass { fileprivate func show() { print("Classe mère") {} {} // Le niveau d'accès ne peut pas être supérieur à celui de la classe mère internal > public internal class SubClass: SuperClass { override internal func show() { print("Sous-classe") {} {} let sup = SuperClass() sup.show() let sub = SubClass() sub.show()
以上程序执行输出结果为:
Classe mère Sous-classe
Les constantes, variables et propriétés ne peuvent pas avoir un niveau d'accès supérieur à celui de leur type.
Par exemple, si vous définissez une propriété de niveau public, mais dont le type est de niveau private, cela n'est pas autorisé par le compilateur.
De même, l'indexeur ne peut pas avoir un niveau d'accès supérieur à celui du type de l'index ou du type de retour.
Si la définition du type d'une constante, d'une variable, d'une propriété ou d'un indexeur est de niveau private, alors elles doivent déclarer explicitement le niveau d'accès en tant que private:
private var privateInstance = SomePrivateClass()
Les niveaux d'accès des getters et setters des constantes, variables, propriétés et indices d'index héritent du niveau d'accès des membres auxquels ils appartiennent.
Le niveau d'accès du setter peut être inférieur à celui du getter correspondant, ce qui permet de contrôler les droits de lecture et d'écriture des variables, des propriétés ou des indices d'index.
class Samplepgm { fileprivate var counter: Int = 0{ willSet(newTotal){ print("Compteur: (newTotal)") {} didSet{ if counter > oldValue { print("Nouvelle quantité (counter" - oldValue)" {} {} {} {} let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
Le niveau d'accès de counter est fileprivate, accessible à l'intérieur du fichier.
以上程序执行输出结果为:
Compteur: 100 Nouvelle quantité 100 Compteur: 800 Nouvelle quantité 700
Nous pouvons déclarer un niveau d'accès pour les méthodes d'initialisation personnalisées, mais il ne peut pas être supérieur au niveau d'accès de la classe à laquelle elles appartiennent. Cependant, le constructeur nécessaire est une exception, son niveau d'accès doit être le même que celui de la classe à laquelle il appartient.
Comme pour les paramètres de fonctions ou de méthodes, le niveau d'accès des paramètres de méthode d'initialisation ne peut pas être inférieur au niveau d'accès de la méthode d'initialisation.
Swift fournit un constructeur par défaut sans paramètres pour les structures et les classes, utilisé pour fournir des opérations d'affectation pour toutes les propriétés, mais sans valeur spécifique.
Le niveau d'accès par défaut des méthodes d'initialisation est le même que le niveau d'accès du type appartenant.
Déclarez l'accès aux droits via le mot-clé required avant chaque méthode init() de la sous-classe.
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()
以上程序执行输出结果为:
10 30 10
Si vous souhaitez déclarer explicitement le niveau d'accès d'un protocole, il est important de vous assurer que ce protocole n'est utilisé que dans le domaine d'application que vous avez déclaré.
Si vous définissez un protocole de niveau d'accès public, les fonctions nécessaires fournies par l'implémentation de ce protocole seront également de niveau d'accès public. Cela diffère des autres types, par exemple, les autres types de niveau d'accès public, leurs membres ont un niveau d'accès interne.
public protocol TcpProtocol { init(no1: Int) {} public class MainClass { var no1: Int // stockage local init(no1: Int) { self.no1 = no1 // initialisation {} {} class SubClass: MainClass, TcpProtocol { var no2: Int init(no1: Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) {} // Nécessite seulement un paramètre pour la méthode pratique 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.no"1) print("res is: \(show.no"1) print("res is: \(show.no"2)
以上程序执行输出结果为:
res is: 20 res is: 30 res is: 50
Vous pouvez étendre les classes, les structures et les ensembles sous réserve de conditions permises. Les membres de l'extension doivent avoir le même niveau d'accès que les membres de la classe originale. Par exemple, si vous étendez un type public, les membres que vous ajoutez devraient avoir le même niveau d'accès par défaut internal que les membres originaux.
Ou, vous pouvez explicitement déclarer le niveau d'accès de l'extension (par exemple, utiliser private extension) pour que tous les membres de cette extension aient un niveau d'accès par défaut nouveau. Ce nouveau niveau d'accès par défaut peut toujours être dépassé par un niveau d'accès spécifié pour un membre individuel.
Le niveau d'accès d'un type générique ou d'une fonction générique est le plus bas entre le type générique, la fonction elle-même et les paramètres de type générique.
public struct TOS<T> { var items = [T]() private mutating func push(item: T) { items.append(item) {} mutating func pop() -> T { return items.removeLast() {} {} var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("Paramètres de type") print(tos.items) tos.push("Nom du paramètre de type") print(tos.items) let deletetos = tos.pop()
以上程序执行输出结果为:
["Swift"] ["Swift", "泛型"] ["Swift", "Générique", "Paramètres de type"] ["Swift", "Générique", "Paramètres de type", "Nom du paramètre de type"]
Toute alias de type que vous définissez sera traitée comme un type différent pour faciliter le contrôle d'accès. Le niveau d'accès d'un alias de type ne peut pas être supérieur à celui du type original.
Par exemple, un alias de type de niveau privé peut être attribué à un type public, interne ou privé, mais un alias de type public ne peut être attribué qu'à un type public, pas à un type interne ou privé.
Attention : cette règle s'applique également aux cas où des alias de type sont utilisés pour satisfaire la conformité aux protocoles.
public protocol Container { typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } {} struct Stack<T>: Container { // implémentation originale de Stack<T> var items = [T]() mutating func push(item: T) { items.append(item) {} mutating func pop() -> T { return items.removeLast() {} // conformité au protocole Container mutating func append(item: T) { self.push(item) {} var count: Int { return items.count {} subscript(i: Int) -> T { return items[i] {} {} func allItemsMatch< C1: Container, C2: Container où C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { // vérifiez que les deux conteneurs contiennent le même nombre d'articles si someContainer.count != anotherContainer.count { return false {} // vérifiez chaque paire d'articles pour voir s'ils sont équivalents for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false {} {} // 所有项目匹配,因此返回true return true {} var tos = Stack<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("Where 语句") print(tos.items) var eos = ["Swift", "泛型", "Where 语句"] print(eos)
以上程序执行输出结果为:
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "Where 语句"] ["Swift", "泛型", "Where 语句"]