• 12 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 01/02/2019

Approfondissez les protocoles

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Pour bien appréhender les protocoles, je vous propose que l'on continue à jouer un peu avec dans ce chapitre !

Vous êtes vraiment de grands enfants...
Vous êtes vraiment de grands enfants...

Le point sur les types

Je ne sais pas si vous y avez prêté attention, mais un protocole se déclare un peu comme une énumération, une structure ou une classe.

protocol MonProtocole {}

class MaClasse {}

struct MaStructure {}

enum MonEnumeration {}

Il y a une raison à cela ! Le protocole permet de créer un type, de la même façon que les classes, les structures ou les énumérations. Cela veut dire que vous pouvez écrire cela :

protocol UnProtocole { (...) }

var uneVariable: UnProtocole
var unTableau: [UnProtocole]
func uneFonction(param: UnProtocole) -> UnProtocole { (...) }

La seule différence, c'est que vous ne pouvez pas créer d'instance à partir d'un protocole. En effet, une classe/structure/énumération définit des objets. Vous pouvez donc en créer des instances. Alors que les protocoles définissent seulement des listes d'exigences.

Autrement dit, vous ne pouvez pas écrire :

var uneVariable = UnProtocole()

Euh... Mais alors, ceci ne veut rien dire :

var uneVariable: UnProtocole

Si ! Prenons un exemple avec notre protocole AnimalAnimal est un protocole, donc il définit un type, donc je peux déclarer une variable de type Animal.

var unAnimal: Animal

Animal n'est pas un objet, donc je ne peux pas créer une instance d'Animal. Mais tant mieux, car on a vu qu'Animal était un concept trop abstrait. En revanche, je peux définir cette variable de type Animal.

Cela signifie qu'elle pourra prendre comme valeur une instance de n'importe quelle classe qui implémente le protocole Animal . On peut donc écrire ceci :

var unAnimal: Animal
unAnimal = Dog()
unAnimal = Bird()

Mais unAnimal change de type dans ton exemple ! C'est interdit en Swift !

Eh non ! unAnimal garde le type Animal, seulement celui fonctionne avec Dog et Bird , car ces deux classes se conforment au protocole Animal.

On peut alors faire des trucs sympas avec les protocoles, comme ceci :

var monTableauDAnimaux: [Animal] = [Dog(), Bird()]

On a un tableau qui contient des objets qui ne sont pas du même type, mais qui se conforment tous au type Animal. Lorsque je vais programmer en utilisant mon tableau d'animaux, je vais programmer autour de l'interface définie par mon protocole : je ne me soucie pas de savoir quel type d'animal je manipule. C'est une bien meilleure pratique qui rend mon code plus modulaire !

Des protocoles partout !

Jusqu'à présent, on a parlé uniquement de classe qui se conforme à un protocole, mais sachez que n'importe quel type peut se conformer à un protocole. On peut donc écrire ceci :

protocol MonProtocole {}

class MaClasse: MonProtocole {}

struct MaStructure: MonProtocole {}

enum MonEnumeration: MonProtocole {}

Cela fonctionne exactement de la même manière !

Avant, seulement les classes pouvaient partager des comportements, grâce à l'héritage. Mais les structures et les énumérations n'ont pas l'héritage.

Grâce aux protocoles, toutes les structures de données peuvent partager des comportements ! Encore mieux, une classe peut partager des méthodes avec une énumération.

Plusieurs protocoles

Une même classe/structure/énumération peut se conformer à plusieurs protocoles. En effet, un protocole est simplement une liste d'exigences. De ce fait, on peut combiner ces listes pour obtenir une plus grande liste.

Je vous propose donc que l'on rajoute un deuxième protocole. On va appeler ce protocole Nameable. Et il sera implémenté par toute classe qui veut pouvoir avoir un nom et un prénom :

protocol Nameable {
    var firstName: String { get set }
    var lastName: String { get set }

    func getFullName() -> String
}

Notre classe Dog va adopter le protocole. Lorsqu'une classe adopte plusieurs protocoles, on sépare ceux-ci par une virgule :

class Dog: Animal, Nameable { (...) }

Ensuite, il suffit de répondre à ses exigences.

class Dog: Animal, Nameable {
    var firstName: String = ""
    var lastName: String = ""

    func getFullName() -> String {
        return firstName + " " + lastName
    }

    // (...)    
}

En résumé

  • Un protocole définit un type au même titre qu'une classe/structure/énumération.

  • Un protocole peut être adopté par une classe, une structure, une énumération ou même un autre protocole.

  • Une classe/structure/énumération peut se conformer à plusieurs protocoles. Dans ce cas, on sépare les protocoles avec des virgules.

Exemple de certificat de réussite
Exemple de certificat de réussite