Javascript (21) - Classes, encapsulation et héritage

Dans cette leçon vidéo, l’instructeur explique comment créer et manipuler des classes en JavaScript. Après un rappel rapide des trois méthodes précédentes de création d’objets (objet littéral, constructeur Object, fonction constructeur), il introduit la syntaxe de classe (mot‑clé `class`, convention de capitalisation) et montre comment instancier une classe avec `new`. Il détaille le rôle du `constructor`, l’utilisation de `this` pour initialiser les attributs, et la façon de passer des arguments au moment de l’instanciation. Ensuite, il montre comment ajouter des méthodes ordinaires, puis comment définir des getters et setters (`get` / `set`) pour accéder ou modifier les attributs comme s’ils étaient des propriétés. Le cours aborde la visibilité des membres : les attributs sont publics par défaut, mais il présente l’attribut privé expérimental préfixé par `#` et explique ses limites. Enfin, il décrit l’héritage avec le mot‑clé `extends`, l’appel du constructeur parent via `super`, et montre comment étendre une classe en ajoutant de nouveaux attributs tout en réutilisant le code existant. Tout au long de la vidéo, le formateur exécute le code dans la console, montre les résultats et souligne les bonnes pratiques et les conventions, tout en rappelant que les classes sont essentiellement du sucre syntaxique pour les développeurs habitués à la POO.
Chapters
Bonjour à tous et bienvenue dans cette nouvelle leçon sur le langage JavaScript. Aujourd'hui nous allons voir les classes. Dans la vidéo précédente nous avons vu comment créer des objets personnalisés en JavaScript. Nous avons utilisé 3 méthodes, à savoir: l'objet littéral, le constructeur Object et la fonction constructeur. Ces 3 méthodes permettent de faire la même chose: créer des objets dotés de leurs propres attributs et méthodes. Cependant, les personnes ayant déjà programmé en orienté objet avec d'autres langages comme C++, Java ou PHP sont habituées à une technique commune pour créer des objets qui s'articulent autour des classes. En effet, l'entité qui donne lieu aux objets du programme est bel et bien une classe. Une classe est une structure qui décrit l'objet qui en sera l'instance. D'ailleurs, on parle de l'instanciation de classe pour désigner la création de l'objet. En JavaScript, il est également possible de créer ses propres classes exactement comme on le fait dans d'autres langages de programmation orientés objet. Or, certains développeurs trouvent que la technique des classes en JavaScript est une sorte de sucre syntaxique ou syntactic sugar en anglais, car les classes n'apportent pas vraiment de nouvelles fonctionnalités par rapport aux méthodes de création d'objets vues précédemment, mais elles servent juste à rendre le code plus agréable à voir et surtout, ils permettent de s'aligner avec la syntaxe utilisée dans d'autres langages de programmation orientée objet, ce qui facilite aux développeurs habitués à ce paradigme de coder en JavaScript. Notez que dans cette leçon, je ne vais pas traiter les fondements de la programmation orientée objet à classes mais seulement vous montrer comment manipuler les classes en JavaScript et comment faire certaines opérations fondamentales de la POO comme l'héritage. Mais si vous voulez apprendre davantage à propos de la POO, je vous invite à consulter ma série sur la programmation orientée objet en PHP où j'ai encerclé tout ce qui a rapport avec ce paradigme de programmation et qui est valable pour les autres langages de programmation orientée objet. Pour créer une classe, on utilise la syntaxe suivante: on met le mot-clé class suivi du nom de celle-ci, par exemple Profile. Notez qu'il est de coutume de capitaliser le nom de la classe, c'est-à-dire mettre la première lettre en majuscule, mais ce n'est pas une obligation. En effet, ça reste simplement une convention. On peut faire ça aussi, on peut mettre le nom de la classe égal le terme classe. Ça donne le même résultat, mais je préfère la première syntaxe. Déjà avec ça, je peux instancier ma classe pour créer l'objet qui en sera la concrétisation. On va appeler l'objet candidat et on instancie la classe avec le mot-clé new comme ceci. On mettra de préférence let pour gérer la portée. Alors exécutons ce code. Ça ne donne aucune erreur bien que la classe ne contient rien. Affichons dans la console la valeur de candidat, qui est un objet dans ce cas. Ça nous affiche objet et vous avez constaté qu'entre les accolades on n'a rien parce qu'on n'a pas encore déclaré les membres. Et les membres ce n'est rien d'autre que les attributs et les méthodes. Pour initialiser les attributs, on fait souvent appel au constructeur. Le constructeur n'est rien d'autre qu'une fonction qui sera appelée automatiquement suite à l'instanciation de la classe. En JavaScript, on spécifie le constructeur comme ça. Le mot-clé constructor et ensuite on va spécifier les attributs en mettant le mot-clé this pour faire référence à l'objet qui sera l'instance de la classe. Par exemple nom égal et on va spécifier une valeur. On va dire par exemple Tom. Et pour l'âge, on mettra par exemple 30 ans. Alors là, on vient de spécifier 2 attributs qui sont nom et âge. Maintenant, réaffichons notre objet. Maintenant, ça nous donne bien que c'est un objet qui contient 2 attributs nom et âge avec les valeurs respectives. Cependant, il ne faut pas fixer les valeurs comme ça, on va plutôt les passer en guise d'arguments. Alors ici, je passerai 2 arguments que j'appellerai nom et âge, mais faites attention, le nom qui est là n'a rien à voir avec la variable nom qui est ici. Là, c'est juste une variable normale et là, c'est un attribut, c'est-à-dire c'est une variable qui appartient à l'objet qui sera l'instance de la classe. Alors ici on mettra nom, c'est-à-dire l'argument que j'ai passé je vais l'affecter, et là c'est age. N'oublie pas que le constructeur est exécuté automatiquement suite à l'instanciation de la classe, c'est-à-dire au moment de l'exécution de la ligne 7 dans ce cas. Alors au moment de l'instanciation je vais passer 2 arguments comme ça, c'est-à-dire que désormais le constructeur va accueillir 2 arguments dans l'ordre. Tom et 30. Réexécutons. On obtient le même résultat. Alors là c'est la bonne méthode, c'est-à-dire au lieu de fixer les attributs directement, vaut mieux les initialiser au sein du constructeur de la classe. Maintenant on va créer une méthode qui permettra d'afficher ces valeurs par exemple. On va l'appeler info. C'est une fonction et qui va nous retourner quelque chose. Imaginez que nous voulons qu'elle nous retourne les 2 valeurs, c'est-à-dire le nom et l'âge et va les retourner en tant qu'objets. On remettra l'objet, la clé nom pointe sur la valeur this->nom pour dire l'attribut courant et pareil pour la clé age. Maintenant on va appeler la méthode info ici comme ça. Réexécutons et ça nous affiche l'objet retourné. Bien sûr on peut retourner une chaîne de caractères, un nombre comme vous souhaitez mais là j'ai préféré retourner toutes les valeurs de mes attributs d'un seul coup. Avec leur clé. Alors j'ai trouvé que l'objet est le meilleur type qui va me procurer ceci. Maintenant on va créer une autre méthode qui permettra de changer le nom. On va l'appeler renommer. On va lui passer un argument, par exemple le nouveau nom. On va mettre nom comme d'habitude. Et n'oubliez toujours pas, le nom que j'ai passé en argument ici ou ici n'ont rien à voir avec l'attribut nom. Et pour éviter les confusions, vous pouvez les renommer si vous souhaitez. Et ensuite je vais changer l'attribut nom et en lui affectant la valeur de l'argument. Alors avant d'appeler la méthode info, je vais renommer le nom. Alors l'objet s'appelle candidat et j'appelle la méthode renommer à laquelle je passe le nouvel argument qui est dans ce cas Ben. Alors la prochaine fois que j'afficherai les informations, il m'affichera Ben et non pas Tom. Voilà. Notez qu'il existe deux méthodes spéciales en orienté objet qu'on appelle le getter et le setter. En français, on les appelle respectivement l'accesseur et le mutateur. En JavaScript, on peut les programmer comme ça: on mettra le mot-clé get puis on déclare une fonction qui s'appelle par exemple recNom pour dire récupérer le nom. Alors dans ce cas, recNom c'est un getter ou accesseur si vous souhaitez. Il est préfixé par le mot get. Le getter, il va tout simplement me retourner un attribut. Dans ce cas, on va dire que ça va me retourner le nom. D'ailleurs, comme son nom l'indique, on va mettre un little s, point nom comme ça. La particularité de la méthode getter, c'est qu'on peut la traiter en tant qu'attribut, c'est-à-dire que désormais req->nom, ça deviendra un attribut, non pas une fonction. Maintenant, je vais afficher req->nom. Si je fais comme ça, ça va m'afficher une erreur parce que pour le moteur JavaScript, il s'agit d'un getter. Donc il doit être manipulé en tant qu'attribut. Réexécutons. Ça me donne que ce n'est pas une fonction. En effet, il faut retirer les parenthèses et traiter la méthode comme étant un attribut. Dans ce cas, cet attribut vaut la valeur qui est retournée par la fonction. Réexécutons et ça me donne Ben. Alors là, c'est le getter. Ça permet généralement d'accéder aux attributs avec un nom différent. Notez que ça, c'est le cas pour JavaScript, mais dans d'autres langages de programmation, le getter est traité un peu différemment. Le principe reste le même. De la même manière, on peut spécifier le setter, le setter ou bien le mutateur. Ce dernier permet de modifier la valeur d'un attribut. Et comme pour le getter, on va préfixer par set. On va créer un mutateur qui change le nom, par exemple. On va l'appeler changerNom comme ça. Et dans ce cas, le getter accepte un seul argument qui est le nouveau nom. Dans ce cas, bon, je vais l'appeler nom aussi si vous voulez. Et dedans, je mettrai s.nom. Égal la nouvelle valeur de nom. De la même manière, quand j'aurai appelé cette fonction ou bien cette méthode, il va agir sur l'attribut nom pour le changer. Bon, ça fait exactement la même chose que la méthode renommer. La seule différence, c'est que désormais cette méthode sera vue par JavaScript comme étant un attribut. Alors au lieu d'appeler la méthode renommer ici, je vais mettre chNom. Mais là aussi, ça va générer une erreur parce que JavaScript va me dire ça c'est pas une méthode. En effet, dans que ça soit une méthode, mais en fait il faut la traiter comme étant un attribut. Alors en exécutant, alors on a une erreur, ça me dit aussi la même chose, c'est pas une fonction. Là ce que je vais faire, c'est juste lui affecter la valeur souhaitée, dans ce cas Ben, c'est-à-dire je vais traiter la méthode comme étant un attribut. Maintenant c'est bon, la valeur a été appliquée et je l'ai affichée. Alors dans cet exemple, j'ai exécuté le setter pour modifier la valeur du nom et j'ai exécuté le getter pour afficher ce dernier. Bien sûr, on peut créer autant de getters et de setters que l'on souhaite et chacun va manipuler un attribut différent. Imaginez maintenant que je veux accéder à cet attribut directement, par exemple nom, je veux l'afficher en dehors de la classe, c'est-à-dire un peu plus loin ici. Je mettrai par exemple console.log nom ou bien age si vous voulez. Alors on mettra candidat.age. Dans ce cas, on est censé afficher la valeur de l'âge dans la console et ça affiche 30 sans le moindre problème. Parce qu'en réalité, les attributs et aussi les méthodes ont une visibilité publique, c'est-à-dire qu'ils sont accessibles depuis l'intérieur de la classe comme depuis l'extérieur. Et ce principe en programmation orientée objet s'appelle encapsulation, c'est-à-dire la manière avec laquelle vous voulez gérer la visibilité de vos membres. Notez que dans la plupart des cas, on préfère que les attributs soient manipulables uniquement depuis l'intérieur de la classe. C'est-à-dire qu'on veut que leur visibilité soit privée. Si vous voulez faire ceci, bien que je vous conseille pas cette méthode parce que c'est encore en cours d'expérimentation, mais ça marche sur la plupart des navigateurs. Par exemple, on va déclarer le nom en tant qu'attribut et on va le préfixer par dièse. Ça veut dire désormais que cet attribut est privé. De la même manière ici, au moment de l'instanciation, je vais mettre #nom. Alors dans ce cas, le nom c'est un attribut privé. Bien sûr, le nom qui est là est différent du nom qui est là parce que là c'est un attribut privé, là c'est un autre attribut. Maintenant si je veux afficher le nom ici, comme ça avec le dièse, pour dire je veux afficher l'attribut privé, ça me donne bien qu'il n'y a pas de référence pour cet attribut privé. C'est-à-dire que le principe d'encapsulation est maintenant appliqué avec une visibilité qui est privée pour les attributs. Et ça c'est ce qui se fait généralement dans la plupart des langages de programmation orientée objet. Mais en JavaScript c'est encore dans ses balbutiements, c'est-à-dire que c'est une méthode qui est en phase d'expérimentation. D'ailleurs, la proposition est publiée sur GitHub. Alors on va retirer ça, on va supposer que nos attributs sont publics, ce qui est le cas par défaut. Maintenant, il reste à explorer un principe fondamental de la programmation orientée objet, c'est l'héritage. L'héritage n'est rien d'autre que de créer une classe qui va hériter de tous les membres de la classe mère, c'est-à-dire la classe qui va lui donner vie. Alors voilà ce qu'on va faire, on a déjà créé la classe qui s'appelle Profil. Maintenant on va créer une autre classe qui s'appelle ProfilÉtendu si vous voulez. Imaginez que dans cette classe je veux exploiter ce que j'ai déjà ici, c'est-à-dire les mêmes attributs et méthodes qui ont été déclarés avant. Dans ce cas il suffit de procéder à l'héritage comme ça avec le mot-clé extends et je mets le nom de la classe mère, c'est-à-dire la classe principale. Alors désormais je viens de créer une classe qui a hérité de tous les attributs et méthodes de la classe précédente ou bien la classe mère qui est Profil dans ce cas. Alors c'est comme si je prends tout ce code et que je le colle ici. Regardez d'ailleurs au moment de l'instanciation, au lieu d'instancier la classe Profil, je vais instancier la classe Profil étendu. J'exécute et j'ai bien les 2 méthodes qui s'exécutent correctement. Je vais cacher ça pour le moment, ça aussi, c'est-à-dire je vais juste afficher le nom à l'aide du getter dans ce cas. Et ça m'affiche Tom parce que je n'ai pas modifié la valeur du nom. Alors c'est la valeur qui est passée au moment de l'instanciation qui est conservée. Maintenant imaginez que je veux ajouter un autre attribut qui s'appelle spécialité, que j'ajouterai au profil parce que pour le moment j'ai que 2 informations, à savoir le nom et l'âge. Pour ajouter la spécialité, alors j'imagine que je vais créer un constructeur dans la classe Fille. D'ailleurs la classe qui hérite de la classe Mère, on l'appelle une classe Fille. On va mettre ici le constructeur et on lui passe les arguments souhaités. Dans ce cas, il y aura 3 arguments, à savoir le nom, l'âge et la spécialité. Et ici, au lieu de refaire le même traitement, c'est-à-dire this.nom égale à nom, c'est-à-dire que j'initialise tous les attributs au moment de l'instanciation, D'ailleurs, je vais passer la spécialité ici, par exemple informatique. Alors, vous constatez que le code est redondant, c'est-à-dire que j'ai déjà un bout de code qui est déclaré ici et que je répète. Alors, au lieu de répéter ça, il suffit d'appeler le constructeur de la classe Mère. Et pour faire ceci, on fait appel à la méthode super tout simplement, c'est-à-dire c'est comme si on fait appel à la classe du niveau supérieur, mais on va lui passer les arguments nécessaires à l'exécution, c'est-à-dire le nom et l'âge. Alors super, c'est exactement comme si vous appelez le constructeur en lui passant les arguments, ça donnera la même chose. Maintenant ici au lieu d'appeler le getter, je vais afficher directement la valeur spécialité. Exécutons et ça me donne un fou. Alors là c'est toute la puissance de l'héritage, c'est-à-dire au lieu de réécrire un code entièrement, on utilise un code déjà existant dans la classe mère et on l'étend avec ce que l'on veut ajouter. Soit de nouveaux attributs ou bien de nouvelles méthodes. Alors j'espère que vous avez compris comment utiliser les classes en JavaScript et comme je l'ai souligné au début de la vidéo, vous avez le choix entre 4 méthodes différentes pour manipuler vos objets en JavaScript. Généralement, elles font toutes la même chose, mais ça reste juste une question de préférence, c'est-à-dire il serait préférable d'adopter la méthode où vous êtes le plus à l'aise. Merci pour votre attention et à la vidéo prochaine.
More from Yamossoun

Algorithme de calcule de la racine carrée par dichotomie #dichotomy #squareroot #algorithm









