Les classes

Les classes

28 February 2022

Programmer en procédurale, c'est bien, mais en orienté objet, c'est mieux. Nous allons voir comment créer une classe JavaScript afin de créer des objets. Beaucoup de nouveau mots que nous allons détailler dans les parties suivantes.

La syntaxe

Une classe est un fichier contenant un ensemble de fonctions spéciales que nous pourront utiliser directement sur un objet par la suite.

La syntaxe d'une classe se fait comme suit :

class MaMaison {
    // ...
}

Dans l'exemple, ma classe JavaScript se nomme Maison précédé du mot clé class. Vous remarquerez que le nom est en UpperCamelCase.

Par convention, le fichier contenant cette classe portera le même nom : `MaMaison.jsˋ.

Utilisation

Une fois votre classe définie, il suffira de l'appeler par son nom :

let maison = new MaMaison();

Vous venez d’instancier votre classe et de créer votre premier objet, ˋmaisonˋ. L’objet ˋmaisonˋ contiendra toutes les méthodes contenues dans la classe ˋMaMaisonˋ.

Le nombre d’objets pouvant être créé à partir d’une classe est illimitée. Il faut bien comprendre aussi qu’un objet est indépendant.

Le constructeur

Le constructeur est une méthode automatiquement appelée par le mot clé new lors de l'instanciation de votre objet.

Dans la classe, rajoutons ce constructeur :

class MaMaison {
    constructor() {
        console.log('Bonjour !');
    }
}

Maintenant, instanciez votre classe et vous verrez que le console.log s'active automatiquement.

Nous pouvons aussi passer des arguments au constructeur que nous utiliserons dans une autre méthode :

class MaMaison {
    constructor(color) {
        this.color = color;
    }

    myColor() {
        alert(this.color);
    }
}

let objet = new MaMaison('Verte');
objet.myColor();

Au moment de l'instanciation de mon objet, je passe une valeur à ma classe, Verte, qui sera transmise au constructeur automatiquement appelé. Cette valeur sera stockée dans une variable globale interne this.color que je réutilise potentiellement dans n'importe quelle méthode de ma classe. Dans mon cas de figure, je passe cette variable dans un alert.

Autre exemple d'utilisation :

class MaMaison {
    constructor(color) {
        this.color = color;
    }

    myColor() {
        alert(this.color);
    }

    isPurple() {
        if (this.color === 'purple') {
            alert('Purple !');
        }

        alert('Si tu veux...');
    }
}

let objet = new MaMaison('purple');
objet.isPurple();

J'ai créé une nouvelle méthode isPurple() contenant une condition sur la couleur de la maison que j'ai passé en paramètre de ma classe MaMaison au moment de son instanciation. Si la couleur correspond à purple, alors une alerte s'affichera contenant la phrase Purple !, sinon le texte Si tu veux... s'affichera dans l'alerte.

La syntaxe - Version 2

Il est possible de nommer vos classes grâce aux expressions anonymes ou nommées.

// Anonyme
let MaMaison = class {
    constructor(color) {
        this.color = color;
    }
}

// Nommée
let maison = class MaMaison {
    constructor(color) {
        this.color = color;
    }
}

Getter & Setter

La classe peut inclure des getters (mutateurs) et setter (accesseur). Pour rappel, il s'agit de méthodes permettant pour le setter de définir une valeur à une propriété et au getter de retourner la valeur d'une propriété.

class MaMaison {
    constructor(color) {
        // Appelle le setter automatiquement
        this.color = color;
    }

    set color(value) {
        this._color = color;
    }

    get color() {
        return this._color;
    }

    myColor() {
        alert(this.color);
    }
}

let objet = new MaMaison('Purple');
alert(objet.color);

Quand le constructeur sera appelé par l'instanciation et qu'il devra fournir la valeur reçue à la variable, il appellera automatiquement le setter qu'il lui est associé, car comme vous l'avait vu dans le code ci-dessus, le getter et le setter porte le nom de la variable.

Extends

On peut étendre une classe à une autre pour que la première profite de toutes les méthodes à disposition. Créons une seconde classe :

class Terrain {
    constructor(surface) {
        this.surface = surface;
    }
}

Étendons la classe fille MaMaison à la classe parente Terrain grâce au mot clé extends.

class MaMaison extends Terrain {
    constructor(color, surface) {
        super(surface);
        this.color = color;
    }

    mySurface() {
        alert(`Le terrain ${this.color} est de ${this.surface} m2`);
    }
}

Dorénavant, MaMaison profite des variables et méthodes contenues dans la classe Terrain, mais l'inverse est impossible.

Dans le constructeur, j'ai volontairement ajouté un nouvel argument surface pour passer la valeur à ma classe parent Terrain. Je n'ai pas utilisé le mot clé this, mais la méthode super(), sans quoi il m'est impossible d'envoyer la valeur à classe parente Terrain.

Faites bien attention à utiliser super() avant le mot clé this, sinon une erreur de type Uncaught ReferenceError: must call super constructor before using 'this' in derived class constructor sera générée.

Il ne vous reste plus qu'à utiliser votre objet comme d'habitude, celui hérite de toutes les méthodes de son parent.

let objet = new MaMaison('Purple', 1234);
objet.mySurface();

// Résultat : Le terrain Purple est de 1234 m2