Comprendre les classes en JavaScript : Fondamentaux de la programmation orientée objet

Anastasia Frezefond
5 min readJun 22, 2023

--

Les classes en JavaScript offrent une approche puissante pour organiser et structurer le code en utilisant le paradigme de programmation orientée objet (POO). Elles permettent d’organiser et de structurer le code, facilitant ainsi la lisibilité, la ré-utilisabilité, la maintenabilité et la conception de logiciels modulaires.

Un concept abstrait de “moule” pour créer des objets

Une classe définit les propriétés (variables) et les méthodes (fonctions) qui seront présentes dans les objets créés à partir de cette classe. Elle agit comme un « moule » à partir duquel nous pouvons créer des instances d’objets ayant des caractéristiques et des comportements spécifiques.

Et du coup, c’est quoi une instance d’une classe ?

C’est une copie concrète de la classe avec ses propres valeurs de propriétés et sa capacité à appeler les méthodes définies dans la classe. Lorsque vous créez une instance d’une classe, vous utilisez le mot-clé new suivi du nom de la classe et des arguments nécessaires pour le constructeur de la classe. Cela crée une nouvelle instance unique de la classe avec ses propres caractéristiques.

Par exemple, si nous avons une classe Person avec les propriétés name et age, nous pouvons créer des instances individuelles de cette classe pour différentes personnes. Dans cet exemple, person1 et person2 sont des instances distinctes de la classe Person, chacune avec ses propres valeurs pour les propriétés name et age.

Nous pouvons définir des méthodes à l’intérieur de la classe en utilisant la syntaxe des fonctions, en les ajoutant comme des propriétés de la classe. Les méthodes peuvent accéder aux propriétés de l’objet en utilisant this. Chaque instance a également accès à la méthode greet() définie dans la classe, qu'elle peut appeler pour afficher une chaine de caractères personnalisée.

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}

const person1 = new Person("Alice", 30);
const person2 = new Person("Bob", 25);

person1.greet(); // Hello, my name is Alice and I'm 30 years old.
person2.greet(); // Hello, my name is Bob and I'm 25 years old.

C’est quoi le rôle du constructeur ?

Le constructeur d’une classe en JavaScript sert à initialiser les propriétés d’un objet lors de sa création. C’est une méthode spéciale qui est automatiquement appelée lorsque vous créez une nouvelle instance de la classe. Il est utilisé pour initialiser les propriétés de l’objet et effectuer d’autres opérations nécessaires avant que l’objet ne soit utilisé.

Dans le constructeur, nous pouvons définir les propriétés de l’objet à l’aide du mot-clé this. Dans l’exemple précédent, le constructeur de la classe Person prend deux paramètres, name et age, et utilise le mot-clé this pour définir les propriétés name et age de l'objet en cours de création.

Le principe d’héritage

L’héritage est un concept important en programmation orientée objet qui permet de créer une classe basée sur une autre classe existante. Une classe héritante (ou sous-classe) hérite les propriétés et les méthodes de la classe parente (ou superclasse).

L’un des principaux avantages des classes en JavaScript est la possibilité d’utiliser l’héritage pour créer des classes enfants qui héritent des propriétés et des méthodes d’une classe parente. Cela permet de réutiliser du code et de créer une hiérarchie de classes.

Prenons l’exemple de la classe Person et créons une classe enfant appelée Employee qui hérite des propriétés et des méthodes de la classe Person.

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}

class Employee extends Person {
constructor(name, age, position) {
super(name, age); // Appel du constructeur de la classe parente
this.position = position;
}

work() {
console.log(`${this.name} is working as an ${this.position}.`);
}
}

Dans cet exemple, la classe Employee étend la classe Person à l'aide du mot-clé extends et ajoute une propriété position spécifique aux employés. Le constructeur de la classe Employee utilise également super(name, age) pour appeler le constructeur de la classe parente (Person) et initialiser les propriétés name et age.

Maintenant, nous pouvons créer une instance de la classe Employee et accéder aux méthodes héritées de la classe Person, ainsi qu'à la méthode spécifique à la classe Employee

const employee = new Employee("Anastasia", 36, "Astronaut");
employee.greet(); // Hello, my name is Anastasia and I'm 36 years old.
employee.work(); // Anastasia is working as an Astronaut.

Cela démontre comment l’héritage permet à la classe Employee d'étendre les fonctionnalités de la classe Person tout en bénéficiant de ses propriétés et méthodes déjà définies. Cela facilite la réutilisation du code et la gestion des différents types d'objets dans votre application.

Le concept d’encapsulation

L’encapsulation est un autre concept important lié aux classes. Dans le contexte de la programmation, l’encapsulation consiste à regrouper des données et des méthodes qui les manipulent au sein d’une entité, appelée objet.

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

getName() {
return this.name;
}

setName(newName) {
this.name = newName;
}

getAge() {
return this.age;
}

setAge(newAge) {
if (newAge >= 0) {
this.age = newAge;
}
}
}

Dans cette classe Person, les propriétés name et age sont définies en tant que variables d'instance. Elles ne sont pas accessibles directement de l'extérieur de la classe.

Les méthodes getName() et getAge() fournissent un moyen de récupérer respectivement le nom et l'âge de la personne. En encapsulant ces propriétés et en fournissant des méthodes d'accès, nous contrôlons la lecture des informations.

Voici un exemple d’utilisation de la classe Person :

const person = new Person("John", 30);

console.log(person.getName()); // John
console.log(person.getAge()); // 30

person.setName("Jane");
person.setAge(25);

console.log(person.getName()); // Jane
console.log(person.getAge()); // 25

L’encapsulation nous permet ainsi de protéger les données de la personne et d’offrir des méthodes pour y accéder et les modifier de manière contrôlée.

La notion de polymorphisme

La notion de polymorphisme fait référence à la capacité d’un objet à prendre différentes formes ou à se comporter différemment en fonction du contexte. Cela signifie qu’un même nom ou une même méthode peut être utilisé(e) pour effectuer des actions différentes en fonction des objets auxquels il s’applique.

class Person {
constructor(name) {
this.name = name;
}

introduce() {
console.log(`Hi, my name is ${this.name}.`);
}
}

class Student extends Person {
constructor(name, grade) {
super(name);
this.grade = grade;
}

introduce() {
console.log(`Hi, I'm ${this.name} and I'm in grade ${this.grade}.`);
}
}

class Teacher extends Person {
constructor(name, subject) {
super(name);
this.subject = subject;
}

introduce() {
console.log(`Hello, I'm ${this.name} and I teach ${this.subject}.`);
}
}

Dans cet exemple, nous avons une classe de base Person avec une méthode introduce() qui permet à une personne de se présenter.

Ensuite, nous avons deux classes qui héritent de Person : Student (étudiant) et Teacher (professeur). Chaque classe enfant a sa propre implémentation de la méthode introduce() pour représenter l'introduction spécifique à l'étudiant et au professeur.

Maintenant, nous pouvons créer des instances de différentes personnes et les traiter de manière polymorphe :

const person1 = new Person("John");
const person2 = new Student("Alice", 9);
const person3 = new Teacher("Mr. Smith", "Mathematics");

person1.introduce(); // Hi, my name is John.
person2.introduce(); // Hi, I'm Alice and I'm in grade 9.
person3.introduce(); // Hello, I'm Mr. Smith and I teach Mathematics.

En résumé, le polymorphisme nous permet de traiter des objets de différentes classes héritant d’une classe de base (comme Student et Teacher héritant de Person) de manière uniforme en utilisant une interface commune. Cela nous permet de simplifier le code, de favoriser la ré-utilisabilité et de permettre une gestion plus générique des objets dans une hiérarchie de classes.

--

--