• 8 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 28/05/2024

Surchargez les méthodes

Surchargez les méthodes

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 ! Ça va être super !

Utilisez 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 fait 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)
   }
}

Utilisez override

Chauffe Marcel !

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 :

Notre diagramme de classes avec nos 6 classes : Bus et SchoolBus, Road, RoadSection, HomeRoadSection et SchoolRoadSection
Notre diagramme de classes

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 n’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 ?

Eh 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 soit 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 sayHello() {
      print("Bonjour")
   }

 

   func describeYourself() {
      print("Je suis un animal.")
   }
}

Maintenant prenons une classe fille Dog :

class Dog: Animal {
}

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

class Dog: Animal {
   override func sayHello() {
      print("Wouf !")
   }

 

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

Voyons un peu ce que j'ai fait ici. J'ai modifié la méthode sayHello . 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 describeYourself , j'appelle la méthode describeYourself 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 ajoutant "Et pas n'importe lequel : un chien !". Du coup, si j'écris :

let dog = Dog()
dog.describeYourself()

… la console affiche :

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

À vous de jouer !

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.

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.

Exercice 3

Le contenu de l’exercice se trouve dans le dossier Github P3C3.

  1. Ouvrez un nouveau Playground Xcode.

  2. Copiez le contenu du fichier “main.swift” dans votre Playground.

  3. Suivez les instructions.

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.

Vous avez appris dans ce chapitre les subtilités de l’héritage allié aux méthodes, maintenant regardons ensemble comment mieux gérer les types que vous avez créés avec l’héritage !

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