Swift - Protocoles
Les protocoles fournissent un modèle pour les méthodes, les propriétés et d'autres fonctionnalités d'exigences. Il est simplement décrit comme un squelette de méthodes ou de propriétés au lieu d'une implémentation. L'implémentation des méthodes et des propriétés peut en outre être effectuée en définissant des classes, des fonctions et des énumérations. La conformité d'un protocole est définie comme les méthodes ou propriétés satisfaisant aux exigences du protocole.
Syntaxe
Les protocoles suivent également la syntaxe similaire à celle des classes, des structures et des énumérations -
protocol SomeProtocol {
// protocol definition
}
Les protocoles sont déclarés après les noms de classe, de structure ou de type d'énumération. Les déclarations de protocole unique et multiple sont également possibles. Si plusieurs protocoles sont définis, ils doivent être séparés par des virgules.
struct SomeStructure: Protocol1, Protocol2 {
// structure definition
}
Lorsqu'un protocole doit être défini pour une super classe, le nom du protocole doit suivre le nom de la super classe avec une virgule.
class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
// class definition
}
Exigences relatives aux propriétés et aux méthodes
Le protocole est utilisé pour spécifier une propriété de type de classe ou une propriété d'instance particulière. Il spécifie simplement le type ou la propriété d'instance seule plutôt que de spécifier s'il s'agit d'une propriété stockée ou calculée. En outre, il est utilisé pour spécifier si la propriété est «gettable» ou «configurable».
Les exigences de propriété sont déclarées par le mot clé «var» en tant que variables de propriété. {get set} est utilisé pour déclarer des propriétés gettable et définissable après leur déclaration de type. Gettable est mentionné par la propriété {get} après sa déclaration de type.
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 4 Protocols"
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 4"
studdet.marks = 98
studdet.markssecured()
print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
98
true
false
Swift 4 Protocols
Swift 4
Exigences de la méthode de mutation
protocol daysofaweek {
mutating func print()
}
enum days: daysofaweek {
case sun, mon, tue, wed, thurs, fri, sat
mutating func print() {
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.print()
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
Wednesday
Configuration requise pour l'initialiseur
Swing permet à l'utilisateur d'initialiser les protocoles pour suivre une conformité de type similaire à celle des initialiseurs normaux.
Syntaxe
protocol SomeProtocol {
init(someParameter: Int)
}
Par exemple
protocol tcpprotocol {
init(aprot: Int)
}
Implémentations de classe des exigences de l'initialiseur de protocole
Un initialiseur désigné ou pratique permet à l'utilisateur d'initialiser un protocole pour se conformer à sa norme par le mot-clé réservé «requis».
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// initializer implementation statements
}
}
protocol tcpprotocol {
init(aprot: Int)
}
class tcpClass: tcpprotocol {
required init(aprot: Int) {
}
}
La conformité du protocole est assurée sur toutes les sous-classes pour une implémentation explicite ou héritée par le modificateur «requis».
Lorsqu'une sous-classe remplace son exigence d'initialisation de super classe, elle est spécifiée par le mot-clé modificateur 'override'.
protocol tcpprotocol {
init(no1: Int)
}
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 print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
res is: 20
res is: 30
res is: 50
Protocoles en tant que types
Au lieu d'implémenter des fonctionnalités dans un protocole, elles sont utilisées comme types de fonctions, de classes, de méthodes, etc.
Les protocoles sont accessibles sous forme de types dans -
Fonction, méthode ou initialiser comme paramètre ou type de retour
Constante, variable ou propriété
Tableaux, dictionnaires ou autres conteneurs en tant qu'éléments
protocol Generator {
typealias members
func next() -> members?
}
var items = [10,20,30].generate()
while let x = items.next() {
print(x)
}
for lists in map([1,2,3], {i in i*5}) {
print(lists)
}
print([100,200,300])
print(map([1,2,3], {i in i*10}))
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]
Ajout de la conformité de protocole avec une extension
Le type existant peut être adopté et conforme à un nouveau protocole en utilisant des extensions. De nouvelles propriétés, méthodes et indices peuvent être ajoutés aux types existants à l'aide d'extensions.
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 de protocole
Swift 4 permet aux protocoles d'hériter des propriétés de ses propriétés définies. Il est similaire à celui de l'héritage de classe, mais avec le choix de lister plusieurs protocoles hérités séparés par des virgules.
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(sum: 1)
}
}
class classb: result {
func print(target: classa) {
target.calc(sum: 5)
}
}
class student: classa {
var no1: Int = 10
func calc(sum: Int) {
no1 -= sum
print("Student attempted \(sum) times to pass")
if no1 <= 0 {
print("Student is absent for exam")
}
}
}
class Player {
var stmark: result!
init(stmark: result) {
self.stmark = stmark
}
func print(target: classa) {
stmark.print(target: target)
}
}
var marks = Player(stmark: student2())
var marksec = student()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam
Protocoles de classe uniquement
Lorsque des protocoles sont définis et que l'utilisateur souhaite définir un protocole avec des classes, il doit être ajouté en définissant d'abord la classe suivie de la liste d'héritage du protocole.
protocol tcpprotocol {
init(no1: Int)
}
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 print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
res is: 20
res is: 30
res is: 50
Composition du protocole
Swift 4 permet d'appeler plusieurs protocoles à la fois à l'aide de la composition du protocole.
Syntaxe
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 print(celebrator: 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)
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)
Vérification de la conformité du protocole
La conformité du protocole est testée par des opérateurs «est» et «comme» similaires à ceux du type casting.
L'opérateur is renvoie true si une instance est conforme à la norme du protocole et renvoie false en cas d'échec.
le as? La version de l'opérateur downcast renvoie une valeur facultative du type de protocole, et cette valeur est nulle si l'instance n'est pas conforme à ce protocole.
La version as de l'opérateur downcast force le downcast au type de protocole et déclenche une erreur d'exécution si le downcast échoue.
import Foundation
@objc protocol rectangle {
var area: Double { get }
}
@objc class Circle: rectangle {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
var area: Double
init(area: Double) { self.area = area }
}
class sides {
var rectsides: Int
init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]
for object in objects {
if let objectWithArea = object as? rectangle {
print("Area is \(objectWithArea.area)")
} else {
print("Rectangle area is not defined")
}
}
Lorsque nous exécutons le programme ci-dessus en utilisant aire de jeux, nous obtenons le résultat suivant -
Area is 12.5663708
Area is 198.0
Rectangle area is not defined