Vous commencez maintenant à avoir une bonne idée de ce qu'est la POO. Et dans ce chapitre, nous allons découvrir ce qui fait toute sa puissance : l'héritage !
Découvrez l'héritage
Comme c'est un chapitre important, je ne vais pas arriver à vous l'expliquer tout seul. C'est la raison pour laquelle je vous présente Bob, mon assistant dans ce chapitre.
Essayons de représenter Bob en orienté objet. Bob a une taille, un poids et une couleur, il peut aboyer, courir, manger, dormir.
Certes, on pourrait le décrire plus précisément, mais ce n'est déjà pas mal. Laissez-moi maintenant vous présenter Raoul.
Raoul et Bob sont évidemment très différents. Essayons de décrire Raoul en orienté objet. Raoul a une taille, un poids et une couleur. Il peut cracher du feu, manger, dormir, voler.
Hmmm... Selon notre classification, il semblerait que les classes Dragon
et Dog
ne soient pas si différentes. La plupart de leurs propriétés et méthodes sont identiques. Donc si on devait écrire l'implémentation des méthodes, on ferait deux fois la même chose. Or un développeur déteste se répéter ! On va donc utiliser l'héritage !
L'héritage permet de créer un arbre de classe. Dans notre exemple, nous avons deux animaux qui partagent des caractéristiques communes. En fait, on aurait pu décrire une classe Animal
comme ceci :
Oui, mais le problème, c'est qu'on a été obligé d'enlever certaines méthodes comme bark
ou fly
, car elles ne sont pas valables pour tous les animaux. Il faut que l'on puisse garder nos classes Dog
et Dragon
pour gérer ces spécificités.
Alors que fait-on ? Nous allons modifier Dog
et Dragon
pour supprimer tout ce qui est commun, et qui du coup peut être mis dans la classe Animal
. Et on va dire que les classes Dragon
et Dog
héritent de la classe Animal
. On peut dire que Dragon
et Dog
sont les classes "filles" de la classe "mère", Animal
.
Mais qu'est-ce que ça veut dire, "hérite de" ?
Eh bien, très concrètement, lorsque la classe Dog
hérite de la classe Animal
, toutes les propriétés et méthodes de la classe Animal
sont disponibles dans la classe Dog
. C'est comme si je les avais écrites dans la classe Dog
. Je peux écrire par exemple :
let bob = Dog()
bob.taille = 120
bob.weight = 30
bob.eat()
Les propriétés et méthodes de l'exemple ci-dessus ne sont pas définies dans la classe Dog
, mais dans la classe Animal
; et en héritant de cette classe, la classe Dog
les récupère. L'héritage, c'est juste ça.
Mettez l'héritage en action
Avant d'aborder l'implémentation de l'héritage, laissez-moi vous donner un exemple d'héritage en iOS. Je vous l'ai dit en introduction, en iOS, tout est objet. Et la plupart d'entre eux utilisent l'héritage !
iOS et l'héritage
C'est notamment très clair pour l'interface graphique. L'interface graphique est pleine de composants. Il peut y avoir des images, des boutons, des labels, etc. Ces composants vont être disposés sur l'interface et ont donc beaucoup de choses en commun : leur taille, leur position, leur couleur, s'ils sont visibles ou non, s'ils réagissent au toucher ou non, et beaucoup d'autres. C'est la raison pour laquelle ils héritent tous d' UIView
, une classe qui gère tous ces aspects et permet donc à tous les composants de ne pas avoir à répéter toute cette logique. Il suffit qu'ils en héritent !
Le bus scolaire et l'héritage
Prenons un autre exemple, mais cette fois-ci avec notre bus scolaire. En début de cours, nous avions créé ensemble le diagramme suivant :
En utilisant l'héritage, nous allons pouvoir modifier ce schéma et rajouter quelques classes :
Alors, regardons un peu tout cela. Tout d'abord nous allons ajouter la classe SchoolBus
. Cette classe hérite de la classe Bus
. La classe SchoolBus
définit un bus scolaire. La différence avec un bus classique, c'est que le bus scolaire va avoir une propriété en plus : schoolName
. Car le bus scolaire est associé à une école. Par ailleurs, la méthode drive
de SchoolBus
va être légèrement différente de la méthode drive
de Bus. Car le bus scolaire va s'arrêter à chaque maison pour récupérer les enfants et ensuite les déposer à l'école, tandis que le bus simple roule seulement sur la route.
Par ailleurs, nous avons deux autres nouvelles classes : HomeRoadSection
et SchoolRoadSection
, qui héritent toutes les deux de RoadSection
. Chacune de ces trois classes va avoir des initialisations différentes qui vont nous permettre de dessiner sur le canevas des sections de route, avec ou sans maison et avec ou sans école. La classe HomeRoadSection
a en plus une variable children
qui va nous permettre de savoir combien d'enfants le bus va récupérer dans telle maison.
Implémentez l'héritage
Voici venu le moment que vous attendez tous ! Comment fait-on dans le code pour dire qu'une classe hérite d'une autre ? Eh bien, comme pour beaucoup de choses avec Swift, c'est très simple !
Essayons de créer notre classe SchoolBus
qui hérite de Bus
. Il suffit d'écrire la création de classe comme on a l'habitude de le faire :
class SchoolBus {
}
Et maintenant, pour appliquer l'héritage, on ajoute :
puis la classe dont on veut hériter ( Bus
, en l'occurrence) :
class SchoolBus: Bus {
}
Alors que l'implémentation de SchoolBus
semble vide, je peux utiliser toutes les propriétés et méthodes de Bus
:
var schoolBus = SchoolBus(driverName: "Joe")
schoolBus.seats = 50
schoolBus.drive(road: road)
C'est la beauté de l'héritage. Maintenant je vais rajouter une propriété spécifique à SchoolBus
:
class SchoolBus {
var schoolName = ""
}
La propriété schoolName
sera disponible dans la classe SchoolBus
, mais pas pour les instances de Bus
.
Et voilà ! Je vous l'avais promis, l'héritage avec Swift, c'est simple.
À vous de jouer !
Le contenu de l’exercice se trouve dans le dossier Github P3C1.
Ouvrez un nouveau Playground Xcode.
Copiez le contenu du fichier “main.swift” dans votre Playground.
Suivez les instructions.
En résumé
Une classe (dite fille) peut hériter d'une autre classe (dite mère). Dans ce cas, toutes les propriétés et méthodes de la classe mère sont disponibles dans la classe fille, sans que la classe fille ait besoin de les redéfinir.
L'héritage permet d'organiser son code grâce à un arbre d'héritage, et d'éviter ainsi des répétitions.
Pour qu'une classe hérite d'une autre, on utilise les
:
suivis du nom de la classe mère :
class Daughter: Mother {
}
Vous pouvez être fiers de vous, l’héritage n’est pas une mince affaire mais vous vous en sortez super bien ! On continue ensemble dans le prochain chapitre pour parler des énumérations, et voir comment elles vont nous aider dans notre projet de bus scolaire.