• 20 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/1/19

Surchargez les méthodes

Log in or subscribe for free to enjoy all this course has to offer!

Dans le chapitre précédent, nous avons utilisé une énumération pour modifier l'initialisation de la classe RoadSection, ce qui nous a permis d'écrire ceci :

RoadSection(type: .plain)
RoadSection(type: .home)
RoadSection(type: .school)

C'est déjà bien, mais ce n'est pas exactement l'objectif souhaité. À l'origine, nous souhaitions utiliser l'héritage pour initialiser différents types de sections de route. On aimerait plutôt pouvoir écrire ceci :

RoadSection()
HomeRoadSection()
SchoolRoadSection()

Alors, allons-y !

Ca va être super !

Je vous propose de commencer tout simplement par déclarer nos classes HomeRoadSection et SchoolRoadSection en les faisant hériter de RoadSection :

class HomeRoadSection: RoadSection {
}

class SchoolRoadSection: RoadSection {
}

C'est un bon début. Maintenant nous allons les initialiser en dessinant sur le canevas la section de route correspondante :

class HomeRoadSection: RoadSection {
    init() {
    }
}

class SchoolRoadSection: RoadSection {
    init() {
    }
}

Et là, réfléchissons un peu. Nous avons déjà fait le travail dans l'initialisation de RoadSection pour que la bonne section de canevas soit dessinée en fonction de son type. Est-ce qu'il n'y aurait pas un moyen de réutiliser l'initialisation de RoadSection dans ses classes filles ?

Vous vous en doutez, il y a moyen. Et le moyen, c'est super ! Oui le mot super. Le mot super dans une classe permet de faire référence à la classe mère de la classe dans laquelle on se trouve. C'est un peu l'équivalent du mot self. Sauf que self fais référence à soi-même alors que super fait référence à la classe mère.

Donc ici, nous allons utiliser super pour récupérer l'initialisation de RoadSection :

class HomeRoadSection: RoadSection {
    init() {
        super.init(type: .home)
    }
}

class SchoolRoadSection: RoadSection {
    init() {
        super.init(type: .school)
    }
}

Maintenant, voyons ce qu'il se passe si j'écris ceci :

HomeRoadSection()

Je vais tout d'abord appeler l'initialisation de HomeRoadSection. Ensuite, je vais, par le mot clé super, appeler l'initialisation de RoadSection en lui passant le paramètre .home. Cela nous fait passer dans un switch qui appelle la méthode : canvas.createHomeRoadSection().

Maintenant, je vous propose de rajouter la propriété children à la classe HomeRoadSection qui va nous permettre de savoir combien d'enfants habitent la maison. J'en profite en même temps pour l'inclure dans notre initialisation.

class HomeRoadSection: RoadSection {
    var children: Int

    init(children: Int) {
        self.children = children
        super.init(type: .home)
    }
}

À la conduite !

Nos sections de route sont maintenant très pratiques, mais notre bus scolaire a encore triste mine :

class SchoolBus: Bus {
    var schoolName = ""
}

Pourtant nous avions de grands projets pour lui, souvenez-vous :

Nous voulions lui ajouter une fonction drive.

Mais SchoolBus hérite de Bus?!

Oui... Et ?

Du coup, il a déjà à disposition la fonction drive qui est définie dans Bus !

Eh oui ! Bien vu ! Mais la fonction drive de Bus ne fait que conduire le long de la route sans s'arrêter. Alors que le bus scolaire lui doit s'arrêter à chaque maison, récupérer les enfants et ensuite s'arrêter à l'école.

On a qu'à changer la méthode drive directement dans Bus.

Oui, mais ce serait un peu faux. Un bus normal ne s'arrête pas devant les maisons et ne va pas à l'école.

Alors qu'est-ce qu'on fait ?

Et bien on utilise l'override !

L'overquoi ?

L'override est une technique qui permet à une classe fille de réécrire une méthode de la classe mère.

Imaginons que la méthode drive est un DVD sur lequel se trouve l'épisode 4 de Star Wars. Il existe deux façons de faire l'override :

  • Soit on grave sur le DVD l'épisode 3 (avant) et / ou l'épisode 5 (après) en plus de l'épisode 4.

  • Soit on efface tout et on met Bambi. ;)

Autrement dit l'override permet à une classe fille de compléter l'implémentation d'une méthode la classe mère ou de la réécrire complètement. Dans les deux cas, comment fait-on ?

On utilise tout simplement le mot-clé override. Regardons ça avec un exemple. Prenons la classe Animal suivante :

class Animal {
    func saluer() {
        print("Bonjour")
    }

    func seDécrire() {
        print("Je suis un animal.")
    }
}

Maintenant prenons une classe fille Chien :

class Chien: Animal {

}

Pour redéfinir les méthodes, il me faut rajouter le mot-clé override avant ma fonction :

class Chien: Animal {
    override func saluer() {
        print("Wouf !")
    }

    override func seDécrire() {
        super.seDécrire()
        print("Et pas n'importe lequel : un chien !")
    }
}

Voyons un peu ce que j'ai fait ici. J'ai modifié la méthode saluer. Désormais elle n'affiche plus "Bonjour", mais "Wouf !". La méthode a été entièrement modifiée, on ne réutilise rien de la méthode originale. En revanche, dans la méthode seDécrire, j'appelle la méthode seDécrire de la classe Animal en utilisant le mot clé super comme pour l'initialisation de tout à l'heure. Ensuite, je complète la méthode en rajoutant "Et pas n'importe lequel : un chien !". Du coup, si j'écris :

let unChien = Chien()
unChien.seDécrire()

La console affiche :

Je suis un animal.
Et pas n'importe lequel : un chien !

Exercices

Ce que nous avons appris dans ce chapitre va vous permettre d'améliorer notre programme !

Exercice 1

En vous inspirant de la fonction createStraightRoad, créez une fonction createRoadToSchool qui permet de créer une route ayant les caractéristiques suivantes :

  • Une longueur de route de 30

  • Toutes les 7 sections, une section contient une maison

  • La dernière section contient une école Pour cet exercice, vous utiliserez les classes HomeRoadSection et SchoolRoadSection que nous avons ajoutées dans ce chapitre.

// Ne regardez pas la correction


































static func createRoadToSchool() -> Road {
    let road = Road(length: 0)
    for i in 0..<30 {
        if i%7 == 1 {
            road.sections.append(HomeRoadSection(children: 2))
        } else {
            road.sections.append(RoadSection(type: .plain))
        }
    }
    road.sections.append(SchoolRoadSection())
    return road
}

Exercice 2

En utilisant la technique de l'override, vous implémenterez la méthode drive de la classe SchoolBus. Le bus doit marquer un arrêt à toutes les maisons et à l'école.

// Ne regardez pas la correction




































override func drive(road: Road) {
    for section in road.sections {
        switch section.type {
        case .standard:
            moveForward()
        case .home:
            stop()
            moveForward()
        case .school:
            stop()
        }
    }
}

Exercice 3

Entraînez-vous avec cet exercice !

En résumé

  • Le mot-clé super permet d'accéder dans une classe fille à l'implémentation d'une méthode ou d'une initialisation de la classe mère.

  • Le mot-clé override permet de modifier dans une classe fille une méthode définie dans une classe mère soit en la complétant soit en la redéfinissant complètement.

Example of certificate of achievement
Example of certificate of achievement