Thanks!
X
Paypal
Github sponshorship
Patreon

Rust

Fork me on GitHub

II. Spécificités de Rust

2. Les enums

Les "enums" sont très différentes de celles que vous pourriez croiser dans des langages impératifs comme le C ou le C++. Elles ne représentent pas juste des nombres mais bien plus :

Runenum UneEnum {
    Variant,
    VariantStruct { a: i32, b: i32 },
    VariantTuple(String),
}

Chaque "champ" d'un enum est appelé un variant. Comme vous avez pu le voir au-dessus, les enums permettent beaucoup plus. Il est cependant aussi possible de déclarer et utiliser des enums plus proches de celles que vous pourriez trouver en C/C++ :

Run#[derive(Debug)]
enum UneEnum {
    Variant = 12,
    Variant2,
}

UneEnum::Variant vaudra donc 12, par-contre UneEnum::Variant2 ne vaudra pas 13 ! Il vous faudra donner une valeur à chaque variant si vous voulez que ce soit le cas.

Utilisation

Les enums peuvent se révéler très utile dans beaucoup de cas. Par-exemple, vous avez codé un jeu-vidéo qui fonctionne au tour par tour (un jeu d'échec ?). Pendant son tour, le joueur peut bouger une pièce ou bien ne rien faire. On peut exprimer ça de la façon suivante :

Runenum Action {
    Bouger { piece: Piece, nouvelle_position: Position },
    Passer,
}

Si le joueur bouge une pièce, on aura Action::Bouger sinon on aura Action::Passer.

Un autre exemple avec du parsing d'adresse IP :

Runenum IPKind {
    IPV4(u8, u8, u8, u8),
    IPV6(u32, u32, u32, u32),
}

Et cette enum s'utiliserait comme ceci :

Runfn parse_ip(ip: &str) -> IPKind {
    // le parsing
}

match parse_ip("127.0.0.1") {
    IPKind::IPV4(_, _, _, _) => {
        println!("c'est une IPv4 !");
    }
    IPKind::IPV6(_, _, _, _) => {
        println!("c'est une IPv6 !");
    }
}

On peut aussi se servir d'une enum pour gérer des erreurs comme le permettent les enums [Result] et [Option] :

Runmatch File::open("fichier.txt") {
    Ok(fichier) => {
        // le fichier existe et on a les droits d'accès, on peut s'en servir !
    }
    Err(e) => {
        // le fichier n'existe pas ou on n'a pas les droits d'accès, on ne peut rien faire...
        println!("Erreur en tentant d'ouvrir le fichier : {:?}", e);
    }
}

Ce sont 2 utilisations très différentes des enums mais qui sont des éléments très importants permettant à Rust d'empêcher ses utilisateurs d'utiliser des types invalides.

Implémenter des méthodes sur une enum

Tout comme pour les structures (que nous verrons dans le chapitre suivant), il est possible d'implémenter des méthodes (et des traits !) sur des enums. Je vais donner un exemple rapide ici mais j'en parle plus en détails dans le chapitre suivant :

Run// On reprend notre enum précédente :
enum IPKind {
    IPV4(u8, u8, u8, u8),
    IPV6(u32, u32, u32, u32),
}

impl IPKind {
    fn is_v4(&self) -> bool {
        match *self {
            IPKind::IPV4(_, _, _, _) => true,
            _ => false,
        }
    }

    fn is_v6(&self) -> bool {
        !self.is_v4() // je suis un peu fainéant :)
    }
}

Je ne vais pas m'étendre plus sur le sujet et vous invite donc à passer au chapitre suivant pour en savoir plus !