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