Pour aller plus loin, nous allons découvrir un nouveau modèle de données nommées ! En Swift, il existe trois modèles de données nommées :
les classes ;
les structures ;
les énumérations.
Ce cours fait la part belle aux classes : vous savez de quoi il s'agit.
Les structures ressemblent beaucoup aux classes et sont très utiles en Swift, mais nous ne verrons leur utilisation qu'au prochain cours sur iOS.
Et les énumérations, eh bien c'est le sujet de ce chapitre !
Découvrez les énumérations
Comme les classes, les énumérations sont des modèles de données nommées. C'est-à-dire qu'elles vont nous permettre de modéliser nos données en définissant un nouveau type. C'est ce qu'on a fait avec nos classes jusqu'à présent. On a créé un modèle de données simple à comprendre, avec trois nouveaux types : un bus, une route et des sections de route. Les énumérations ont une mission similaire, mais pour des usages un peu différents.
Le rôle d'une énumération est très simple : elle permet d'énumérer des cas. Et il y a plein de moments où c'est utile. Laissez-moi vous donner quelques exemples :
Quand vous cherchez votre direction avec une boussole, il y a quatre cas possibles : nord, sud, est, ouest.
Si quelqu’un vous demande votre couleur préférée, il y a huit possibilités : noir, marron, rouge, orange, jaune, vert, bleu ou violet.
Si vous voulez présenter un message d’erreur à un utilisateur, vous pouvez définir plusieurs cas identifiables, comme : Vous n'êtes pas connecté, Connexion Internet faible ou Vous n'avez pas l'autorisation.
Avec les énumérations, on va pouvoir nommer tous ces cas. En reprenant les exemples précédents, cela donnerait :
Type : Direction / Cas : north, south, east, west.
Type : Color / Cas : black, brown, red, orange, yellow, green, blue, violet.
Type : Error / Cas : not connected, low signal, unauthorized.
On a donc un type générique qui contient différents cas. Sans plus attendre, je vous propose de vous montrer tout de suite comment déclarer ces 3 énumérations en Swift :
// 1
enum Direction {
case north
case south
case east
case west
}
// 2
enum Color {
case black
case brown
case red
case orange
case yellow
case green
case blue
case violet
}
// 3
enum Error {
case notConnected
case lowSignal
case unauthorized
}
Comme vous pouvez le constater, cela ressemble aux déclarations de classe. Ici on a le mot-clé enum
qui permet de déclarer l'énumération, et ensuite le mot-clé case
à l'intérieur, qui permet à chaque fois d'ajouter un nouveau cas.
Il existe une syntaxe réduite où l'on peut tout écrire sur une seule ligne. Il suffit d'utiliser la ,
entre deux cas :
// 1
enum Direction {
case north, south, east, west
}
// 2
enum Color {
case black, brown,, red, orange, yellow, green, blue, violet
}
// 3
enum Error {
case notConnected, lowSignal, unauthorized
}
Utilisez les énumérations
Pour utiliser une énumération, on utilise le nom de l'énumération suivi du .
, suivi du nom du cas. Par exemple :
var connectionError = Error.notConnected
var connectionError = Error.notConnected
connectionError = .lowSignal // Le type est connu grâce à la déclaration précédente
let dir: Direction = .north // Le type est annoté
Utilisez les énumérations et switch
On utilise très souvent les énumérations avec les switch
. C'est logique, car le switch est une structure de contrôle qui permet de naviguer entre plusieurs cas. C'est ce que nous allons faire ici avec nos types de sections de route. Tout d'abord, je vous propose de créer une énumération qui décrit nos trois types de sections de route :
enum RoadSectionType {
case plain
case home
case school
}
Maintenant, nous allons pouvoir ajouter à notre classe RoadSection
la propriété type :
class RoadSection {
var type: RoadSectionType
init() {
canvas.createRoadSection()
}
}
Nous allons désormais modifier notre init
. Nous allons créer une initialisation qui prend en compte le paramètre type. Cela va nous permettre de dessiner sur le canevas la partie de route correspondant au type choisi :
init(type: RoadSectionType) {
self.type = type
}
Rien de nouveau ici, j'utilise une initialisation avec paramètre, comme on l'a vu dans les chapitres précédents.
Je vais maintenant rajouter le switch :
init(type: RoadSectionType) {
self.type = type
switch type {
case .plain:
canvas.createRoadSection()
case .home:
canvas.createHomeRoadSection()
case .school:
canvas.createSchoolRoadSection()
}
}
Plusieurs choses à noter :
Pour chaque cas, j'utilise la méthode appropriée du canevas pour dessiner la section.
Je fais le switch sur la variable
type
qui a pour typeRoadSectionType
. Je peux donc utiliser les cas directement avec le point, sans rappelerRoadSectionType
avant.Le switch en Swift doit être exhaustif. Cela veut dire que tous les cas doivent être pris en compte dans un switch. C'est la raison pour laquelle vous avez systématiquement utilisé le mot-clé
default
jusqu'à présent, qui permet de couvrir tous les autres cas. Ici, nous utilisons une énumération qui ne contient que trois cas. Nous couvrons ces trois cas avec le switch, donc inutile d'utiliserdefault
.
Avec cette nouvelle initialisation, nous pouvons maintenant créer facilement les sections de route du type de notre choix, comme ceci :
RoadSection(type: .plain)
RoadSection(type: .home)
RoadSection(type: .school)
Dans le prochain chapitre, nous allons encore simplifier ceci avec l'héritage !
Découvrez la vérité sur les optionnels
En effet, je vais vous révéler la vérité sur les optionnels ! Vous êtes prêts ?
Les optionnels... sont... tout simplement... des... ÉNUMÉRATIONS ! Eh oui ! Laissez-moi vous montrer à quoi ils ressemblent :
enum Optional<T> {
case none
case some(T)
}
Donc un optionnel, c'est deux cas. Soit rien (none), soit quelque chose (d'un type précis). Et c'est exactement ce que vous connaissez des optionnels. Allons plus loin et jouons au jeu des équivalences :
Ces équivalences vous montrent des utilisations assez avancées des énumérations (notamment à cause de cette histoire de <T>
). Ne vous arrêtez pas à ça, et prenez juste le temps de comprendre le fait que les optionnels sont des énumérations, et ce que cela veut dire concrètement.
J'espère que cela vous permettra de vous servir correctement des optionnels !
Ajoutez des valeurs brutes
Jusqu'à présent, nos énumérations sont des coquilles vides. Cela signifie qu'elles ne contiennent rien. Elles nous permettent de définir des cas, mais les cas ne contiennent pas de données. Sachez qu'en Swift, on peut associer à chaque cas une valeur. Reprenons un des exemples précédents :
enum Error {
case notConnected
case lowSignal
case unauthorized
}
Cela pourrait être pratique que les cas contiennent un message d'erreur à afficher à notre utilisateur. Pour cela, nous allons préciser le type de la valeur brute contenue dans chaque cas, et ensuite leur donner des valeurs. Voici la syntaxe :
enum Error: String {
case notConnected = "Vous n'êtes pas connecté."
case lowSignal = "Veuillez vérifier votre connexion internet."
case unauthorized = "Vous n'êtes pas autorisé à effectuer cette action."
}
Je définis donc d'abord que la valeur brute a pour type String, et ensuite je l'attribue à chacun des cas. Ensuite, pour l'obtenir, j'utilise la propriété rawValue
.
let connectionError = Error.notConnected.rawValue // Cela affiche "Vous n'êtes pas connecté.
// 1
enum Direction: String {
case north
case south
case east
case west
}
// 2
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
var dir = Direction.north.rawValue // Contient "nord"
var earth = Planet.earth.rawValue // Contient 3
À vous de jouer !
Le contenu de l’exercice se trouve dans le dossier Github P3C2.
Ouvrez un nouveau Playground Xcode.
Copiez le contenu du fichier “main.swift” dans votre Playground.
Suivez les instructions.
En résumé
Les énumérations, comme les classes et les structures, sont des modèles de données nommés.
Les énumérations permettent d'énumérer des cas.
La syntaxe de création d'une énumération est la suivante :
enum NameOfEnumeration {
case nameOfCase1
case nameOfCase2
case nameOfCase3
}
Pour utiliser une énumération, on utilise le nom de l'énumération suivi de
.
, puis du nom du cas :NameOfEnumeration.nameOfCase1
.On utilise très souvent les énumérations avec les
switch
.Les optionnels sont des énumérations.
Les énumérations peuvent contenir des valeurs, appelées valeurs brutes. Ces valeurs doivent être du même type pour tous les cas d'une énumération. On les rajoute comme ceci :
enum NameOfEnumeration: Type {
case nameOfCase1 = value1
case nameOfCase2 = value2
case nameOfCase3 = value3
}
La valeur brute est contenue dans la propriété
rawValue
.
Vous avez désormais une compétence de plus dans votre bagage POO et Swift ! Maintenant vous allez pouvoir vous servir des énumérations et de l’héritage pour améliorer notre projet dans le prochain chapitre.