Classes et objets dans ECMAScript

View more Tutorials:

1- Votre première classe

ECMAScript 5 ne contient pas de concept explite de la Classe (Class). Au lieu de cela, il stimule une classe basée sur les deux concepts tels que  function & prototype. Parce que ES5 a été introduit en 2011, sa syntaxe a été très populaire jusqu'à présent. Cependant, nous ne pouvons pas nier qu'il est difficile pour des développeurs de comprendre la création d'une classe de cette manière. Pendant ce temps, les langages tels que Java, C#, .. ont un moyen plus moderne de créer une classe. La version ES6, publiée en 2015, corrige rapidement ce problème. Il fournit une syntaxe moderne pour définir une classe.
Avec la nouvelle syntaxe  ECMAScript 6 devient moins compliqué pour des développeurs lorsqu'ils créen une classe et une sous- classe (Subclass). Mais à côté technique, il n'y a pas de changement avec la version précédante.
Ci-dessous, j'ai un rectangle, qui a 2 property importantes telles que width (la largeur) et height (la hauteur). Nous allons définir une classe nommée Rectangle pour la simuler avec la syntaxe ES6.
Créez un fichier de ressources  rectangle.js:
rectangle.js
// Define a class.
class Rectangle  {

    // Un Constructeur a 2 paramètres.
    // (Utilisé pour créer des instantes)
    // this.width fait allusion à property (propriété) width de la classe.
    constructor (width = 5 , height = 10)  {
        this.width = width;
        this.height = height;
    }

    // Une méthode calcule la superficie du rectangle.
    getArea() {
        var area = this.width * this.height
        return area
    }

}

// Créer un objet de la classe Rectangle via Constructor.
var rect = new Rectangle(3, 5);

console.log("Height "+ rect.height);
console.log("Width "+ rect.width);

// Appeler la méthode
let area = rect.getArea();
console.log("Area "+ area );
L'exécution de l'exemple:
Que se passera-t-il lorsque vous créerez un objet à partir du constructor de la classe?
Lorsque vous appelez le  Constructor de la classe, un nouvel objet sera créé et les  property de l'objet sera assignées des valeurs à partir des paramètres.
Dans  ECMAScript chaque classe n'a au maximum qu'un constructor. Comme une fonction, les paramètres du constructor peuvent également contenir une valeur par défaut. Vous pouvez donc créer des objets de différentes manières.
// width = 3, height = 5
let rect = new Rectangle(3, 5);

// width = 15, height = 10 (Default)
let rect2 = new Rectangle(15);

// width = 5 (Default), height = 50
let rect3 = new Rectangle(undefined, 50);


// width = 5 (Default), height = 10 (Default)
let rect4 = new Rectangle();
 

2- Getter & Setter

Avant de donner les concepts de  Getter & Setter, nous allons analyser une situation :
Supposons que nous avons une classe  Person, cette classe comprend une  property nommée  name.
Class Person
class Person  {

    constructor(name) {
      this.name = name;
    }
}
Et vous pouvez accéder à cette  property de l'objet, ou lui assigner une nouvelle valeur sans problème.
// Create an object
let person = new Person("Tom");

// Access to property name.
console.log( person.name); // Tom

// Assign new value to property name.
person.name = "Jerry"; // !!!

console.log( person.name ); // Jerry
Accéder librement à une property et changer sa valeur de l'extérieur de la classe sont vraiment dangereux. Parfois, vous voulez obtenir une property à laquelle il est impossible d'accéder, ou assigner une nouvelle valeur à l'extérieur de la classe. Getter/Setter vous permet de créer une telle property.
Le mot-clé  get placé devant une méthode sans les paramètres de classe permet de créer une property dont le nom correspond au nom de la méthode. Cette méthode sera appelée à chaque fois que le programme aura accès à cette  property.
getter-example1.js
class Person  {

    constructor (name)  {
       // property: __name
       this.__name = name;
    }

    // Getter of property name
    get name()  {
       console.log("Call getter of property 'name'!!");
       return this.__name;
    }

}

// ------------ TEST -----------------

let person = new Person("Tom");

// Access to property 'name' ==> Call getter
console.log( person.name); // Tom

// Assign new value to property name.
person.name = "Jerry"; // Not Working!!!!

// Access to property 'name' ==> Call getter
console.log( person.name); // Tom
 
Le mot-clé s et placé devant une méthode ayant un paramètre de classe permet de créer une property dont le nom correspond au nom de la méthode. Cette méthode sera appelée à chaque fois que le programme assigne une nouvelle valeur à cette  property.
setter-example1.js
class Person  {

    constructor (name)  {
       // property: __name
       this.__name = name;
    }

    // Setter of property name
    set name(newName)  {
       console.log("Call setter of property 'name'!!");
       this.__name = newName;
    }

    // A method
    showInfo()  {
       console.log("Person: " + this.__name);
    }
}

// ------------ TEST -----------------

let person = new Person("Tom");

// Can not access to property 'name'
console.log( person.name); // undefined

// Set new value to property 'name' ==> Call setter
person.name = "Jerry";

person.showInfo(); // Person: Tom
L'exemple d'une  property avec les deux  Getter & Setter :
getter-setter-example.js
class Rectangle  {

    constructor (width = 5 , height = 10)  {
        this.__width = width;
        this.height = height;
    }

    // Getter of property 'width'
    get width()  {
      return this.__width;
    }

    // Setter of property 'width'
    set width(newWidth)  {
      if(newWidth > 0) {
          this.__width = newWidth;
      } else {
          console.log("Invalid width " + newWidth);
      }
    }

}

// ------------ TEST ------------------


var rect = new Rectangle(3, 5);

console.log("Height "+ rect.height); // Height: 5
console.log("Width "+ rect.width); // Width: 3

rect.width = -100;

console.log("Height "+ rect.height); // Height: 5
console.log("Width "+ rect.width); // Width: 3


rect.width = 100;

console.log("Height "+ rect.height); // Height: 5
console.log("Width "+ rect.width); // Width: 100
Les  property avec des préfixes 2 traits de soulignement (__) sont généralement conventionnées par des programmeurs pour qu'ils ne les utilisent pas à l'extérieur de la classe. Cependant, cette convention peut être rompue par quelqu'un autre. Et par conséquent, l'utilisation de telles property est dangereuse.
Si vous voulez obtenir une  property vraiment privée (Private) elle devrait être nommée avec le préfixe qui est hashtag (#). Cependant, ce code ne peut être exécuté qu'avec l'aide de Babel 7 ou une version ultérieure.
Private property
class Something {

  constructor(){

    this.#someProperty = "test";
  }

}

const instance = new Something();

console.log(instance.#someProperty); // undefined
getter-example2.js
class Person  {

    constructor (name)  {
       // Private property: #name
       this.#name = name;
    }

    // Getter of property name
    get name()  {
       console.log("Call getter of property 'name'!!");
       return this.#name;
    }

}

3- Champs statique (Static Field)

Le mot-clé  static apparaît dans les déclarations Getter ou Setter pour vous aider à définir un champ statique ( static field). Vous pouvez accéder aux static fields via un nom de classe.
Des champs statiques ( static field) qui a une valeur fixée (Immuable) sont appelés des champs de constants statiques ( constant static field).
static-field-example1.js
class Employee {

   constructor (fullName, age)  {
     this.fullName = fullName;
     if(age < Employee.MIN_AGE || age > Employee.MAX_AGE)  {
        throw "Invalid Age " + age;
     }
     this.age = age;
   }

   // A static field: MIN_AGE
   static get MIN_AGE() {
      return 18;
   }

   // A static field: MAX_AGE
   static get MAX_AGE() {
     if(!Employee.__MAXA)  {
        Employee.__MAXA = 60;
     }
     return Employee.__MAXA;
   }

   static set MAX_AGE(newMaxAge)  {
      Employee.__MAXA = newMaxAge;
   }

}

// ---- TEST ---------

console.log("Mininum Age Allowed: " + Employee.MIN_AGE);
console.log("Maximum Age Allowed: " + Employee.MAX_AGE);

// Set new Maximum Age:
Employee.MAX_AGE = 65;

console.log("Maximum Age Allowed: " + Employee.MAX_AGE);

let baby = new Employee("Some Baby", 1); // Error!!
 
Vous avez une autre manière de déclarer un champ statique pour une classe. Toutefois, des champs statiques créés de cette manière ne seront pas des constantes (Constants) car leur valeur peut changer. Voici un exemple :
static-field-example2.js
class Employee {

   constructor (fullName, age)  {
     this.fullName = fullName;
     if(age < Employee.MIN_AGE || age > Employee.MAX_AGE)  {
        throw "Invalid Age " + age;
     }
     this.age = age;
   }
}

Employee.MIN_AGE = 18;
Employee.MAX_AGE = 60;

// ---- TEST ---------

console.log("Mininum Age Allowed: " + Employee.MIN_AGE);
console.log("Maximum Age Allowed: " + Employee.MAX_AGE);

// Set new Maximum Age:
Employee.MAX_AGE = 65;

console.log("Maximum Age Allowed: " + Employee.MAX_AGE);

let baby = new Employee("Some Baby", 1); // Error!!

4- Méthoque statique

Le mot-clé  static qui apparaît dans la déclaration d'une méthode de classe vous permet de définir une méthode statique ( static method). Vous pouvez appeler des méthodes statiques via le nom de la classe. Les méthodes statiques ne peuvent pas être appelées via l'objet de la classe. Une méthode statique est souvent utilisée comme fonction d’utilité d’une application.
point.js
class Point {

  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  // Calcule la distance entre les deux points
  static distance( point1, point2) {
    const dx = point1.x - point2.x;
    const dy = point1.y - point2.y;

    return Math.hypot(dx, dy);
  }
}

// --- TEST ---
let point1 = new Point( 5, 10);
let point2 = new Point( 15, 20);

// Distance
let d = Point.distance(point1, point2);

console.log("Distance between 2 points: " + d);

5- Des opérateurs de comparaison de l'objet

Dans  ECMAScript, lorsque vous créez un objet via le constructeur (constructor), il sera une entité réelle qui est créée en mémoire, elle a une adresse spécifiée.

Un opérateur assigné à un objet AA par un objet BB ne crée pas une nouvelle entité sur la mémoire; il indique simplement l'adresse de AA à l'adresse de BB.
L'opérateur === est de comparer deux objets auxquels il indique. Il renvoie true si les deux objets se réfèrent à la même adresse en mémoire. Les opérateurs !== est utilisé pour comparer les deux adresses de deux objets qui indiquent, il renvoie true si les deux objets pointent vers deux adresses différentes.
identify-operator-example.js
// Define a class.
class Rectangle  {
    constructor (width = 5 , height = 10)  {
        this.width = width;
        this.height = height;
    }
    getArea() {
        var area = this.width * this.height;
        return area;
    }
}

// Create object: r1
let r1 = new Rectangle( 20,  10);

// Create object: r2
let r2 = new Rectangle( 20, 10);

let r3 = r1;


let  b12  =   r1 === r2; // false
let  b13  =   r1 === r3; // true

console.log("r1 === r2 ? " + b12); // false
console.log("r1 === r3 ? " + b13); // true


var bb12  = r1 !== r2; // true
var bb13  = r1 !== r3; // false


console.log("r1 !== r2 ? " + bb12); // true
console.log("r1 !== r3 ? " + bb13); // false
L'exécution de l'exemple:

6- Héritage et Polymorphisme

View more Tutorials: