
The video is a French tutorial on object‑oriented programming in PHP, focusing on inheritance. The instructor starts from a previously built Counter class that tracks page visits via a text file. He demonstrates how to create a subclass Audience that extends Counter using the `extends` keyword, showing that the subclass initially inherits all behavior. He adds a new public method `enregistrer` to log the counter value with a timestamp to a separate file, illustrating file handling (`fopen`, `fputs`, `fclose`) and string concatenation. The lesson then explores visibility modifiers: public attributes are accessible everywhere, private attributes are limited to the defining class, and protected attributes are accessible to subclasses, recommending protected for inherited properties. The instructor shows how to declare a private attribute `ID` in the subclass and initialize it in a constructor, explaining that redefining the constructor overwrites the parent’s, so a static call to the parent constructor (`parent::construct()` or `Counter::construct()`) is required to retain parent initialization. He explains method overriding (surcharge) and the need to call the parent method when extending functionality. The tutorial covers class and method restrictions: `final` prevents inheritance or overriding, while `abstract` forces subclasses to implement abstract methods and prevents direct instantiation. He provides examples of errors when violating these rules and demonstrates correct usage. The session concludes with a recap of inheritance principles, best practices for visibility, overriding, and the use of final/abstract modifiers.
Chapters
Bonjour à tous et bienvenue dans cette nouvelle leçon de programmation orientée objet en PHP. Aujourd'hui nous allons voir l'héritage. L'héritage est un des concepts fondamentaux de la programmation orientée objet. Il permet de réutiliser le code d'une classe déjà créée tout en ayant la possibilité de la modifier afin de l'adapter aux nouveaux usages. Pour mieux comprendre comment ça fonctionne, prenons le code suivant: Il s'agit du code de la classe Counter que nous avons déjà vu et qui permet d'implémenter un compteur de visites unique. Dans la page qui s'appelle Counter.php, nous avons effectué un chargement automatique et nous avons instancié la classe Counter, puis nous avons affiché le résultat du compteur, d'où le résultat suivant sur le navigateur. Donc ça nous affiche 21 dans ce cas, et le fichier texte qui contient la valeur du compteur contient à son tour 21. Il s'agit d'un compteur de visites unique, ça veut dire si j'actualise la page à plusieurs reprises il ne se passera rien. Seule la première visite est comptabilisée. Nous allons donc modifier légèrement le comportement de cette classe afin de mieux expliquer l'exemple. Alors je vais commenter cette condition de telle sorte à ce que l'incrémentation du compteur ne soit pas conditionnée par les visites uniques. Autrement dit, à chaque fois qu'on actualisera la page, on aura la valeur du compteur qui change, comme ceci. Comme vous l'avez vu, dans cette classe nous avons créé une méthode qui s'appelle afficher et qui permet de retourner la valeur qui est stockée dans le fichier texte. Que représente la valeur du compteur. Imaginez maintenant que je veux créer une autre méthode qui permet par exemple d'afficher la valeur du compteur à un instant donné. Ça veut dire à un moment donné je voudrais savoir quelle était la valeur du compteur. Dans ce cas je pourrais facilement ajouter une méthode qui permet de faire ceci au sein de la classe Compteur, mais je préfère plutôt créer une autre classe qui permet de faire ce traitement. Mais la nouvelle classe que je vais créer va se comporter presque identiquement de la même manière que la classe Compteur, sauf que je veux lui ajouter la méthode que je souhaite. Alors, la meilleure solution consiste à l'héritage. Donc, nous allons créer un nouveau document qui contiendra le code de la classe que j'appellerai Audience, comme ceci. Donc Audience.class.php, sans oublier de capitaliser le A de Audience parce qu'il s'agit du fichier qui contient la définition de la classe. Et maintenant, on va définir la classe comme ceci. Si je ne fais que ça, alors dans ce cas je serai obligé de copier tout le code de la classe Counter et de mettre dans la classe Audience. Mais je vais plutôt hériter de la classe Counter de cette manière. Le mot-clé extends permet de spécifier un héritage, c'est-à-dire que désormais la classe qui s'appelle Audience hérite de la classe Counter. Techniquement parlant, c'est comme si je prends tout le code qui est contenu dans la classe Counter et je l'ai mis au sein de la classe Audience. C'est-à-dire qu'en état actuel, je peux déjà instancier la classe Audience et elle va se comporter de la même manière que la classe Counter. D'ailleurs, on va essayer de faire ceci. Donc on va aller sur le fichier Counter et au lieu d'instancier Counter, je vais instancier Audience. Bien sûr, le chargement automatique va assurer l'appel du fichier qui contient le code de la classe. Maintenant, exécutons pour voir le résultat. Et ça marche toujours de la même manière, ça veut dire même si la classe Audience est vide, mais réellement elle contient bien le code de la classe Counter puisqu'elle hérite de celle-ci. Mais ce qui m'intéresse pour le moment ce n'est pas d'utiliser la classe Counter telle qu'elle est, mais je voudrais ajouter une méthode qui permet d'enregistrer la valeur du compteur à un moment donné. Et je vais appeler cette méthode enregistrer comme ceci. C'est une méthode publique et qui va enregistrer la valeur du compteur dans un fichier texte qui s'appelle audience.txt, qui est vide dans un premier temps. Alors puisque je vais manipuler un fichier, bon, je vais donc ouvrir celui-ci en mode lecture-écriture, par exemple id= fopen Et je mettrai le mode A+. Ça veut dire que si le fichier n'existe pas, il sera créé, mais puisqu'il existe déjà, alors il sera accessible en lecture et en écriture tout en plaçant le curseur à la fin du fichier. Ensuite, je vais enregistrer la valeur du compteur dans le fichier audience. Donc fputs, l'identifiant de l'ouverture du fichier, et je mettrai ici la valeur du compteur. Mais avant, je mettrai la date souhaitée. Bon, bien sûr, c'est la date actuelle, donc je mettrai la fonction date. Et le format que je veux mettre c'est YMD pour représenter la date selon le format international. Ça veut dire l'année puis le mois puis le jour. Et ensuite je mettrai HIS pour dire aussi l'heure en format 24 heures, les minutes et les secondes. Ensuite je vais concaténer avec deux points et je concatène avec la valeur du compteur actuel. Maintenant si je me réfère au fichier qui s'appelle compteur.class.php, je vais voir que la valeur du compteur est placée dans un attribut qui s'appelle $nbr. Je mettrai donc ici this->nbr parce que n'oubliez pas qu'au moment de l'héritage, tous les membres de la classe Counter seront réutilisés dans la classe Audience, y compris l'attribut nbr. Et maintenant, dans le fichier qui contient du code PHP, je vais solliciter la méthode enregistrer. Dans un premier temps, je vais commenter cette ligne, ça veut dire je veux pas afficher la valeur du compteur, mais j'appellerai la méthode enregistrer. Exécutons maintenant pour voir le résultat. Je vais maintenant me rendre dans le fichier qui s'appelle audience.txt et je trouve qu'il contient bien la date courante et la valeur du compteur qui est 28. Bon, j'actualise encore une fois. Un nouvel enregistrement est ajouté mais c'est ajouté sur la même ligne. Donc je vais forcer un retour à la ligne ici. Donc je vais concaténer avec \r anti-slash n comme ceci. Donc maintenant je vais effacer cette ligne, j'actualise. Voilà, encore une fois. Et voilà, ça marche parfaitement bien. Il y a juste une chose, c'est que si vous faites bien attention, vous allez trouver que les attributs sont publics. Alors ils sont réutilisables de partout, que ce soit à l'intérieur de la classe Counter comme à l'extérieur, y compris à l'intérieur de la classe fille. Parce que quand on procède à l'héritage, dans ce cas, la classe Audience est appelée une classe fille et la classe Counter est appelée une classe mère. Et c'est la fille qui hérite de la mère. Dans ce cas, donc, je vais changer la visibilité, je mettrai private. Ce qui d'ailleurs est conseillé pour les attributs. Exécutons maintenant pour voir le résultat. Et ça m'affiche une erreur comme quoi l'attribut nbr n'est pas reconnu au sein de la classe. Et c'est normal parce que les attributs privés sont accessibles uniquement depuis l'intérieur de la classe concernée qui est Counter dans ce cas et non pas à l'extérieur y compris la classe fille qui est dans ce cas Audience. Donc la meilleure solution c'est de changer la visibilité. En fait il existe un troisième type de visibilité qui est adapté à l'héritage qui s'appelle protected ou bien protégé. En fait la visibilité protégée c'est comme la visibilité privée sauf que les attributs dans ce cas sont aussi accessibles à l'intérieur de la classe fille mais pas à l'extérieur. Autrement dit, désormais je peux réutiliser ces attributs $fp et $nbr dans la classe Audience. Donc maintenant je n'ai pas touché au code de la classe Audience, j'exécute et je vais voir le résultat. Le message d'erreur a disparu et si je me rends dans le fichier texte, je vais voir que ça contient bien la nouvelle valeur. Donc la valeur précédente n'est pas inscrite et c'est normal parce que l'attribut a causé l'erreur, alors il n'a pas pu trouver la nouvelle valeur du compteur. J'actualise encore une fois et voilà, ça marche très bien. Je peux encore améliorer ce code parce qu'en fait vous avez certainement remarqué que j'ai utilisé une simple variable locale qui s'appelle $id qui permet de stocker l'identifiant d'ouverture du fichier audience.txt. Et c'est pas la même chose que nous avons faite dans la classe Counter. Ici il s'agit bien d'un attribut. Donc on va faire la même chose pour la classe Audience. Je vais donc ici déclarer l'attribut privé dans ce cas. Qui s'appelle ID. Et là, je mettrai this.id et là encore this.id. Donc techniquement, j'ai rien changé. En fait, j'ai juste remplacé une variable classique par un attribut. Le comportement sera le même. J'ai actualisé 2 fois et maintenant il y a bien 2 enregistrements qui ont été rajoutés. On est à la ligne 8. Donc maintenant je vais encore faire un test. La ligne 9 vient d'être ajoutée. Mais comme j'ai mentionné dans une vidéo précédente, il est préférable d'initialiser ces attributs dans le constructeur. Nous allons donc créer un constructeur ici dont le rôle est d'initialiser l'attribut ID comme ceci. En fait, l'opération que je viens de faire, c'est la redéfinition du constructeur. Parce que n'oubliez pas que l'héritage consiste à prendre tous les membres qui sont dans la classe mère et les mettre dans la classe fille. Et parmi ces méthodes, il y a le constructeur. Alors le constructeur qui est là, il vient d'être écrasé parce que je l'ai redéfini. C'est-à-dire que si j'exécute le code, ça va pas marcher convenablement. Regardez ce qui va se passer. Il m'affiche bien une erreur comme quoi donc fclose déjà a besoin d'un paramètre qui n'est rien d'autre que l'identifiant de l'ouverture du fichier. Qui est dans ce cas identifiant à fp. Alors il n'est pas reconnu, pourquoi? Parce qu'il est initialisé dans le constructeur et c'est le constructeur de la classe Mère. Ce que je dois donc faire, c'est quoi? C'est conserver le code de la classe Mère dans le constructeur de la classe Fille. La meilleure façon, c'est de procéder à un appel statique de cette manière: compteur::, c'est-à-dire l'opérateur de résolution de portée, et ensuite je mets construct. Ça veut dire que Je prends le code du constructeur de la classe mère et je le mets dans le constructeur de la classe fille et je lui ajoute cette ligne. Dans ce cas, ça devrait marcher. On va encore voir le fichier. Donc la ligne 11, on actualise. Maintenant la ligne 12. Alors ça marche très bien, sauf que je vais pas mettre le nom de la classe Counter, mais je vais plutôt utiliser le mot-clé Parents. Parents, ça veut dire la classe mère. C'est exactement comme le mot-clé self qui fait référence à la classe courante, parent fait référence à la classe Mère qui est Counter. Donc exécutons pour voir le résultat. Donc la ligne 13, la ligne 14, ça veut dire que ça marche très bien. Alors l'opération de redéfinir une méthode s'appelle la surcharge. Quand vous procédez à une surcharge, sachez systématiquement que vous écrasez le code de la méthode de la classe Mère. Pour conserver ce code-là et lui ajouter des instructions supplémentaires, alors il faut toujours procéder à un appel statique de cette manière. Alors vous avez vu l'intérêt de l'héritage, c'est que notre classe d'origine qui est Counter n'a pas été modifiée, mais j'ai pu la réutiliser et ajouter mes propres modifications afin d'adapter le traitement à la nouvelle situation. Cependant, il existe des restrictions que l'on peut appliquer aux classes et aussi aux membres de la classe vis-à-vis de l'héritage. Par exemple, on va aller sur la classe mère qui est Counter. Et avant le mot-clé class on va ajouter le mot-clé final. Dans ce cas on dit que notre classe Counter est finale. Autrement dit c'est une classe que je dois instancier directement et je n'ai pas le droit d'en hériter. Ça veut dire que le code de la classe Audience est erroné parce que tout simplement j'ai procédé à un héritage qui n'est pas permis à l'origine. Regardez ce qui va se passer quand j'exécuterai le code. Ça m'affiche bien qu'on peut pas procéder à un héritage d'une classe finale. Alors si vous souhaitez que votre classe ne soit pas réutilisable, il suffit de lui ajouter la restriction final. Dans ce cas, on peut pas en hériter et on doit l'instancier telle qu'elle est. Sinon, on peut faire ceci: abstract. On parle donc d'une classe abstraite. La classe abstraite, par contre, c'est une classe que l'on ne peut pas instancier directement. Alors il faut impérativement en hériter pour l'exploiter. Dans ce cas, on le code que j'ai écrit est correct parce qu'il a hérité de la classe Counter avant de l'utiliser. Regardez ce qui va se passer. Aucune erreur et j'ai toujours des enregistrements qui vont être rajoutés. Mais maintenant on va essayer d'instancier directement la classe Counter dans le fichier Counter.php. Par exemple ici je vais mettre objet= new Counter. Cette opération n'est pas permise parce que ma classe elle est abstraite donc je peux pas l'instancier directement. Regardez ce qui va se passer, ça m'affiche bien une erreur qui me dit que je peux pas instancier une classe abstraite du nom du compteur. On va éliminer maintenant ce code. Donc alors sachez que vous pouvez toujours ajouter des restrictions à votre classe. Si vous ne mettez rien avant le mot-clé class, dans ce cas votre classe est normale, alors vous pouvez l'instancier directement ou bien d'en hériter et la réutiliser plus tard. Ici vous mettez le mot-clé final, dans ce cas c'est une classe que je dois instancier directement et j'ai pas le droit d'en hériter. Ici vous mettez abstract, dans ce cas ça devient une classe abstraite que je peux pas instancier directement mais je dois impérativement procéder à l'héritage pour pouvoir l'exploiter. Et ces restrictions peuvent aussi se répandre aux membres de la classe, en l'occurrence les méthodes. Ça veut dire si vous avez une méthode particulière comme par exemple afficher dans ce cas, si je lui applique final, Ça veut dire que c'est une méthode que je peux pas surcharger. Autrement dit, quand je vais faire de l'héritage, j'ai pas le droit de définir une méthode qui s'appelle afficher dans la classe Fille. À l'inverse, si je mets abstract, dans ce cas je suis obligé de redéfinir cette méthode dans la classe Fille. On mettra par exemple ici final. Dans ce cas, la méthode afficher est finale. Et je vais aller sur la classe Audience et je vais essayer de créer une autre méthode qui s'appelle afficher. Je mettrai juste echo surcharge de la méthode afficher. J'ai même pas besoin d'appeler cette méthode dans le fichier compteur.php puisque ça va générer une erreur. Et regardez, donc ça me dit que je peux pas réécrire donc la méthode finale du nom de afficher. Donc maintenant je vais essayer de définir une méthode qui est abstraite dans la classe Counter que j'appellerai f et je mets directement deux points. Alors vous avez remarqué que j'ai pas mis d'accordade et c'est normal parce que pour une méthode abstraite on ne doit pas déclarer le corps mais on doit juste définir ce que l'on appelle le prototype de la méthode, à savoir la visibilité, le mot-clé function, le nom de la méthode et entre les parenthèses vous mettez d'éventuels arguments si vous en avez besoin. Vous mettez rien dans le corps. C'est-à-dire que le développeur est obligé de redéfinir une méthode qui s'appelle f dans les classes filles. Rien qu'avec ça, regardez ce qui va se passer quand j'exécute. Ça me dit bien que la classe Audience contient une méthode abstraite qui doit être définie. Alors je suis obligé de la redéfinir. Donc maintenant je vais aller sur la classe Audience et je mettrai Par exemple juste echo test comme ceci. Et bien sûr notez qu'il faut respecter le prototype, ça veut dire il faut mettre la même visibilité et le même nom de la fonction et aussi les mêmes arguments si vous en avez. Donc avec ça je n'aurai plus d'erreurs alors ça marche très bien. Alors pour récapituler, l'héritage est un concept fondamental de la POO. Il permet de réutiliser les codes des classes qui sont déjà créées tout en ayant la liberté de modifier leur traitement pour les adapter à nos besoins. Il est préférable que les attributs de la classe mère soient protégés, comme ça on peut les réutiliser dans la classe fille. Et si vous procédez à une surcharge, ça veut dire la redéfinition d'une méthode déjà déclarée, si vous avez besoin de son traitement, n'oubliez pas de procéder à un appel statique de cette manière. Et ensuite vous ajoutez vos instructions dedans pour qu'elles puissent assurer le nouveau traitement. On peut ajouter des restrictions à nos classes, c'est-à-dire si une classe est abstraite alors on doit impérativement en hériter afin de l'utiliser. Et s'il est final, alors je dois l'instancier directement sans procéder à l'héritage. Même chose pour les membres de la classe et notamment les méthodes. Les méthodes abstraites doivent être redéfinies et les méthodes finales doivent être utilisées directement sans les retoucher. Ça sera tout pour cette séance, 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









