Contrôle d'accès rapide
Le contrôle d'accès peut limiter le niveau d'accès du code dans d'autres fichiers sources ou modules à votre code.
Vous pouvez définir explicitement des niveaux d'accès pour des types individuels (classes, structures, énumérations), ou pour des propriétés, des fonctions, des méthodes d'initialisation, des types de base, des index d'indice, etc.
Les protocoles peuvent également être limités à une certaine portée, y compris les constantes globales, les variables et les fonctions du protocole.
Le contrôle d'accès est basé sur des modules et des fichiers sources.
Le module fait référence à un framework ou une application qui est construit et publié en tant qu'unité indépendante. Dans Swift, un module peut importer un autre module à l'aide du mot-clé import.
Un fichier source est un fichier de code source unique, qui appartient généralement à un module. Un fichier source peut contenir les définitions de plusieurs classes et fonctions.
Swift propose trois niveaux d'accès différents pour les entités dans le code : public, interne et privé.
访问级别 | 定义 |
---|---|
Public | 可以访问自己模块中源文件里的任何实体,别人也可以通过引入该模块来访问源文件里的所有实体。 |
Internal | :可以访问自己模块中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。 |
Private | 只能在当前源文件中使用的实体,称为私有实体。 |
Public est le niveau d'accès le plus élevé et privé est le niveau d'accès le plus bas.
Syntaxe
Déclarer le niveau d'accès d'une entité via les modificateurs public, internal et private :
public class SomePublicClass {} internal class SomeInternalClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 private func somePrivateFunction() {}
Sauf indication contraire, les entités utilisent le niveau d'accès par défaut internal .
Autorisations d'accès au type de fonction
Le niveau d'accès d'une fonction doit être dérivé en fonction du niveau d'accès 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) { // 函数实现 }
Le niveau d'accès de l'une des classes de la fonction, SomeInternalClass, est interne, et le niveau d'accès de l'autre, SomePrivateClass, est privé. Ainsi selon le principe du niveau d'accès du tuple, le niveau d'accès de ce tuple est privé.
Étant donné que le niveau d'accès du type de retour de fonction est privé, vous devez utiliser le modificateur privé pour déclarer explicitement la fonction :private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // 函数实现 }
Déclarez la fonction comme publique ou interne, ou utilisez le niveau d'accès par défaut interne Incorrect.
Autorisations d'accès aux types d'énumération
Le niveau d'accès des membres d'une énumération est hérité de l'énumération. Vous ne pouvez pas déclarer différents niveaux d'accès individuellement pour les membres de l'énumération.
Instance
Par exemple, dans l'exemple suivant, l'énumération Student est explicitement déclarée comme niveau public, puis le niveau d'accès de ses membres Name et Mark sont également publics :
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("学生名: \(studName).") case .Mark(let Mark1, let Mark2, let Mark3): print("学生成绩: \(Mark1),\(Mark2),\(Mark3)") }
Le résultat de l'exécution du programme ci-dessus est :
学生成绩: 98,97,95
Autorisations d'accès aux sous-classes
Le niveau d'accès d'une sous-classe ne doit pas être supérieur au niveau d'accès de la classe parent. Par exemple, si le niveau d'accès de la classe parent est interne, le niveau d'accès de la sous-classe ne peut pas être déclaré public.
public class SuperClass { private func show() { print("超类") } } // 访问级别不能低于超类 internal > public internal class SubClass: SuperClass { override internal func show() { print("子类") } } let sup = SuperClass() sup.show() let sub = SubClass() sub.show()
Le résultat de sortie de l'exécution du programme ci-dessus est :
超类 子类
Constante, variable, attribut, droits d'accès en indice
Constante, variable, attribut ne peut pas avoir un niveau d'accès supérieur à celui de leur type.
Par exemple, vous définissez un attribut de niveau public, mais son type est de niveau privé, ce qui n'est pas autorisé par le compilateur.
De même, un indice ne peut pas avoir un niveau d'accès supérieur à un type d'index ou à un type de retour.
Si le type de définition des constantes, variables, propriétés et index d'indice est de niveau privé, alors ils doivent déclarer explicitement que le niveau d'accès est privé :
private var privateInstance = SomePrivateClass()
Accès Getter et Setter Autorisations
Le niveau d'accès des getters et setters des constantes, variables, propriétés et index d'indice est hérité du niveau d'accès des membres auxquels ils appartiennent.
Le niveau d'accès d'un Setter peut être inférieur au niveau d'accès du Getter correspondant, afin que vous puissiez contrôler les autorisations de lecture et d'écriture des variables, des propriétés ou des index d'indice.
class Samplepgm { private var counter: Int = 0{ willSet(newTotal){ print("计数器: \(newTotal)") } didSet{ if counter > oldValue { print("新增加数量 \(counter - oldValue)") } } } } let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
Le résultat de l'exécution du programme ci-dessus est :
计数器: 100 新增加数量 100 计数器: 800 新增加数量 700
Autorisations d'accès au constructeur et au constructeur par défaut
Initialisation
Nous pouvons personnaliser l'initialisation La méthode déclare un niveau d'accès, mais il ne doit pas être supérieur au niveau d'accès de la classe à laquelle elle appartient. L'exception concerne les constructeurs obligatoires, dont le niveau d'accès doit être le même que celui de la classe à laquelle il appartient.
Comme les paramètres de fonction ou de méthode, le niveau d'accès des paramètres de la méthode d'initialisation ne peut pas être inférieur au niveau d'accès de la méthode d'initialisation.
Méthode d'initialisation par défaut
Swift fournit une méthode d'initialisation sans paramètre par défaut pour les structures et les classes, qui est utilisée pour fournir des opérations d'affectation pour toutes leurs propriétés, mais ne donne pas de valeurs spécifiques.
Le niveau d'accès de la méthode d'initialisation par défaut est le même que le niveau d'accès du type auquel elle appartient. Les
Instances
déclarent les autorisations d'accès en utilisant le mot-clé requis avant la méthode init() de chaque 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()
Le résultat de l'exécution du programme ci-dessus est :
10 30 10
Droits d'accès au protocole
Si vous souhaitez déclarer explicitement un niveau d'accès au protocole, une chose à noter est que vous devez vous assurer que le protocole n'est utilisé que dans le cadre du niveau d'accès que vous déclarez.
Si vous définissez un protocole avec un niveau d'accès public, alors les fonctions nécessaires fournies par le protocole auront également un niveau d'accès public. Ceci est différent des autres types, tels que les autres types avec niveau d'accès public, dont les membres ont un niveau d'accès interne.
public protocol TcpProtocol { init(no1: Int) } public class MainClass { var no1: Int // local storage init(no1: Int) { self.no1 = no1 // initialization } } class SubClass: MainClass, TcpProtocol { var no2: Int init(no1: Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) } // Requires only one parameter for convenient method 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)")
Le résultat de l'exécution du programme ci-dessus est :
res is: 20 res is: 30 res is: 50
Droits d'accès étendus
Vous pouvez effectuer des opérations sur les classes, les structures et les énumérations lorsque les conditions le permettent. Extension. Les membres d’extension doivent avoir le même niveau d’accès que les membres de la classe d’origine. Par exemple, si vous étendez un type public, les nouveaux membres que vous ajoutez doivent avoir le même niveau d'accès interne par défaut que les membres d'origine.
Vous pouvez également déclarer explicitement le niveau d'accès de l'extension (par exemple en utilisant une extension privée) pour déclarer un nouveau niveau d'accès par défaut pour tous les membres de l'extension. Ce nouveau niveau d'accès par défaut peut toujours être remplacé par les niveaux d'accès déclarés par les membres individuels.
Droits d'accès génériques
Le niveau d'accès d'un type générique ou d'une fonction générique est le niveau d'accès le plus bas parmi 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("类型参数") print(tos.items) tos.push("类型参数名") print(tos.items) let deletetos = tos.pop()
Le résultat de l'exécution du programme ci-dessus est :
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "类型参数"] ["Swift", "泛型", "类型参数", "类型参数名"]
Alias de type
Tout alias de type que vous définissez sera traité comme un type différent pour contrôle d'accès facile. Le niveau d'accès d'un alias de type ne peut pas être supérieur au niveau d'accès du type d'origine.
Par exemple, un alias de type de niveau privé peut être défini sur un type public, interne ou privé, mais un alias de type de niveau public ne peut être défini que sur un type de niveau public, pas sur Interne ou types de niveau privé.
Remarque : Cette règle s'applique également à l'alias des types associés pour la conformité du protocole.
public protocol Container { typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } } struct Stack<T>: Container { // original Stack<T> implementation var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } // conformance to the Container protocol 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 where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { // check that both containers contain the same number of items if someContainer.count != anotherContainer.count { return false } // check each pair of items to see if they are equivalent for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } // all items match, so return 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)
Le résultat de l'exécution du programme ci-dessus est :
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "Where 语句"] ["Swift", "泛型", "Where 语句"]