Protocole Swift
Le protocole précise les méthodes et attributs nécessaires à la mise en œuvre d'une fonction spécifique.
Tout type pouvant répondre aux exigences du protocole est dit conforme au protocole.
Les classes, structures ou types d'énumération peuvent suivre le protocole et fournir des implémentations spécifiques pour compléter les méthodes et fonctions définies par le protocole.
Syntaxe
Le format de syntaxe du protocole est le suivant :
protocol SomeProtocol { // 协议内容 }
Pour qu'une classe suive un certain protocole, vous devez ajouter le nom du protocole après le nom du type , séparés par deux points :, dans le cadre de la définition du type. Lorsque vous suivez plusieurs protocoles, séparez-les par des virgules.
struct SomeStructure: FirstProtocol, AnotherProtocol { // 结构体内容 }
Si une classe a une classe parent tout en étant conforme à un protocole, le nom de la classe parent doit être placé avant le nom du protocole, séparé par des virgules.
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { // 类的内容 }
Spécification des attributs
Le protocole est utilisé pour spécifier des attributs d'instance spécifiques ou des attributs de classe sans préciser s'il s'agit d'attributs stockés ou d'attributs calculés. De plus, il faut préciser s'il est en lecture seule ou en lecture et écriture.
Dans le protocole, var est généralement utilisé pour déclarer les attributs d'une variable. { set get } est ajouté après la déclaration de type pour indiquer que l'attribut est lisible et les attributs en lecture seule sont représentés par { get }.
protocol classa { var marks: Int { get set } var result: Bool { get } func attendance() -> String func markssecured() -> String } protocol classb: classa { var present: Bool { get set } var subject: String { get set } var stname: String { get set } } class classc: classb { var marks = 96 let result = true var present = false var subject = "Swift 协议" var stname = "Protocols" func attendance() -> String { return "The \(stname) has secured 99% attendance" } func markssecured() -> String { return "\(stname) has scored \(marks)" } } let studdet = classc() studdet.stname = "Swift" studdet.marks = 98 studdet.markssecured() print(studdet.marks) print(studdet.result) print(studdet.present) print(studdet.subject) print(studdet.stname)
Le résultat de l'exécution du programme ci-dessus est :
98 true false Swift 协议 Swift
Provisions pour la méthode Mutating
Parfois, il est nécessaire de changer son instance dans la méthode.
Par exemple, dans une méthode d'instance d'un type valeur (structure, énumération), le mot-clé mutation est utilisé comme préfixe de la fonction et écrit avant func, indiquant que l'instance à laquelle elle appartient et son instance peut être modifié dans la méthode. La valeur de l'attribut.
protocol daysofaweek { mutating func show() } enum days: daysofaweek { case sun, mon, tue, wed, thurs, fri, sat mutating func show() { switch self { case sun: self = sun print("Sunday") case mon: self = mon print("Monday") case tue: self = tue print("Tuesday") case wed: self = wed print("Wednesday") case mon: self = thurs print("Thursday") case tue: self = fri print("Friday") case sat: self = sat print("Saturday") default: print("NO Such Day") } } } var res = days.wed res.show()
Le résultat de l'exécution du programme ci-dessus est :
Wednesday
Provisions pour les constructeurs
Le protocole peut exiger que ses abonnés implémentent le constructeur spécifié.
Vous pouvez écrire la déclaration du constructeur dans la définition du protocole comme si vous écriviez un constructeur normal, mais vous n'avez pas besoin d'écrire les accolades et l'entité du constructeur. La syntaxe est la suivante : <🎜. >
protocol SomeProtocol { init(someParameter: Int) }Exemple
protocol tcpprotocol {
init(aprot: Int)
}
Le constructeur de protocole spécifie l'implémentation dans la classeVous pouvez implémenter le constructeur dans la classe qui suit le protocole et le spécifier comme constructeur désigné ou la commodité du constructeur de classe. Dans les deux cas, vous devez marquer l'implémentation du constructeur avec le modificateur "required":
class SomeClass: SomeProtocol { required init(someParameter: Int) { // 构造器实现 } } protocol tcpprotocol { init(aprot: Int) } class tcpClass: tcpprotocol { required init(aprot: Int) { } }L'utilisation du modificateur requis garantit que toutes les sous-classes qui suivent ce protocole peuvent également être utilisées comme constructeurs Spécifie de fournir une implémentation explicite ou héritée mise en œuvre. Si une sous-classe remplace le constructeur désigné de la classe parent et que le constructeur est conforme aux dispositions d'un certain protocole, alors l'implémentation du constructeur doit être marquée avec les modificateurs requis et de remplacement :
protocol tcpprotocol { init(no1: Int) } 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" 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
Type de protocoleBien que le protocole lui-même n'implémente aucune fonction, le protocole peut être utilisé comme type. Le protocole peut être utilisé comme d'autres types ordinaires, scénarios d'utilisation :
- comme type de paramètre ou type de valeur de retour dans une fonction, une méthode ou un constructeur
- En tant que type de constante, de variable ou de propriété
- En tant que type d'élément dans un tableau, un dictionnaire ou un autre conteneur
protocol Generator {
typealias members
func next() -> members?
}
var items = [10,20,30].generate()
while let x = items.next() {
print(x)
}
for lists in [1,2,3].map( {i in i*5}) {
print(lists)
}
print([100,200,300])
print([1,2,3].map({i in i*10}))
Le résultat de l'exécution du programme ci-dessus est : 10 20 30 5 10 15 [100, 200, 300] [10, 20, 30]
Ajouter des membres de protocole dans les extensions
Nous pouvons étendre les types existants (classes, structures, énumérations, etc.) via des extensions.
Les extensions peuvent ajouter des attributs, des méthodes, des scripts d'indice, des protocoles et d'autres membres aux types existants.
protocol AgeClasificationProtocol { var age: Int { get } func agetype() -> String } class Person { let firstname: String let lastname: String var age: Int init(firstname: String, lastname: String) { self.firstname = firstname self.lastname = lastname self.age = 10 } } extension Person : AgeClasificationProtocol { func fullname() -> String { var c: String c = firstname + " " + lastname return c } func agetype() -> String { switch age { case 0...2: return "Baby" case 2...12: return "Child" case 13...19: return "Teenager" case let x where x > 65: return "Elderly" default: return "Normal" } } }
Héritage du protocole
Un protocole peut hériter d'un ou plusieurs autres protocoles, et de nouvelles exigences de contenu peuvent être ajoutées en fonction du protocole hérité.
La syntaxe d'héritage des protocoles est similaire à celle des classes. Plusieurs protocoles hérités sont séparés par des virgules :protocol InheritingProtocol: SomeProtocol, AnotherProtocol { // 协议定义 }
Instance
protocol Classa { var no1: Int { get set } func calc(sum: Int) } protocol Result { func print(target: Classa) } class Student2: Result { func print(target: Classa) { target.calc(1) } } class Classb: Result { func print(target: Classa) { target.calc(5) } } class Student: Classa { var no1: Int = 10 func calc(sum: Int) { no1 -= sum print("学生尝试 \(sum) 次通过") if no1 <= 0 { print("学生缺席考试") } } } class Player { var stmark: Result! init(stmark: Result) { self.stmark = stmark } func print(target: Classa) { stmark.print(target) } } var marks = Player(stmark: Student2()) var marksec = Student() marks.print(marksec) marks.print(marksec) marks.print(marksec) marks.stmark = Classb() marks.print(marksec) marks.print(marksec) marks.print(marksec)
Les résultats de l'exécution du programme ci-dessus. Pour :
学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 1 次通过 学生尝试 5 次通过 学生尝试 5 次通过 学生缺席考试 学生尝试 5 次通过 学生缺席考试
Protocole spécifique à la classe
Vous pouvez restreindre le protocole pour qu'il s'adapte uniquement aux types de classe en ajoutant le mot-clé class dans la liste d'héritage du protocole.
Le mot-clé class doit être le premier à apparaître dans la liste d'héritage du protocole, suivi des autres protocoles hérités. Le format est le suivant :
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { // 协议定义 }
Instance
protocol TcpProtocol { init(no1: Int) } 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" 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
Synthèse de protocole
Prise en charge de Swift la synthèse de plusieurs protocoles Ceci est très utile lorsque nous devons suivre plusieurs protocoles en même temps.
Le format de syntaxe est le suivant :
protocol<SomeProtocol, AnotherProtocol>
Exemple
protocol Stname { var name: String { get } } protocol Stage { var age: Int { get } } struct Person: Stname, Stage { var name: String var age: Int } func show(celebrator: protocol<Stname, Stage>) { print("\(celebrator.name) is \(celebrator.age) years old") } let studname = Person(name: "Priya", age: 21) print(studname) let stud = Person(name: "Rehan", age: 29) print(stud) let student = Person(name: "Roshan", age: 19) print(student)
Le résultat de l'exécution du programme ci-dessus est :
Person(name: "Priya", age: 21) Person(name: "Rehan", age: 29) Person(name: "Roshan", age: 19)
Vérifiez la cohérence de le protocole
Vous pouvez utiliser les opérateurs is et as pour vérifier si un certain protocole est suivi ou une conversion forcée vers un certain type. L'opérateur
is
est utilisé pour vérifier si une instance遵循
possède un certain协议
.as?
Renvoie une valeur facultative qui renvoie le type de protocole lorsque le protocole遵循
est instancié ; sinon,nil
est renvoyé.as
est utilisé pour forcer la conversion vers le bas. Si la conversion forcée échoue, une erreur d'exécution se produira.
Exemple
L'exemple suivant définit un protocole HasArea, nécessitant une zone lisible de type Double :
protocol HasArea { var area: Double { get } } // 定义了Circle类,都遵循了HasArea协议 class Circle: HasArea { let pi = 3.1415927 var radius: Double var area: Double { return pi * radius * radius } init(radius: Double) { self.radius = radius } } // 定义了Country类,都遵循了HasArea协议 class Country: HasArea { var area: Double init(area: Double) { self.area = area } } // Animal是一个没有实现HasArea协议的类 class Animal { var legs: Int init(legs: Int) { self.legs = legs } } let objects: [AnyObject] = [ Circle(radius: 2.0), Country(area: 243_610), Animal(legs: 4) ] for object in objects { // 对迭代出的每一个元素进行检查,看它是否遵循了HasArea协议 if let objectWithArea = object as? HasArea { print("面积为 \(objectWithArea.area)") } else { print("没有面积") } }
La sortie d'exécution du programme ci-dessus Le résultat est :
面积为 12.5663708 面积为 243610.0 没有面积