Voilà enfin le quatrième article sur la POO (Programmation orientée objet) avec WinDev®. Si vous ne les avez pas lu, je vous invite à lire les articles précédents sur la POO.

Aujourd'hui, nous allons parler d'héritage. C'est un des outils offerts par la POO pour mettre en place le polymorphisme.

On hérite du vivant de ses parents

Lorsqu'on parle d'héritage, on pense la plupart du temps à ce moment triste et douloureux où l'on récupère les biens d'un membre proche de sa famille qui vient de décéder. Cet épisode malheureux de la vie n'a aucun rapport avec la POO !

Si je devais faire une analogie, l'héritage serait plutôt lié au principe de la naissance et plus exactement à la transmission de l'héritage génétique d'un parent à son enfant. C'est donc dans la joie et la bonne humeur que nous pouvons continuer à développer !

Le mot clé hérite

Dans WinDev, la mise en place de l'héritage se fait au moyen du mot clé hérite. Une classe enfant hérite de son parent.

Voyons voir l'utiliser l'exemple de deux classes : cParent et cEnfant qui hérite de la première.

Cela donne dans le code de déclaration des deux classes :

Dans cParent :

cParent est une Classe
    ...
FIN

Dans cEnfant :

cEnfant est une Classe
    hérite de cParent
    ...
FIN

Dans notre exemple, on voit que l'enfant n'hérite que d'un seul parent. Avec WinDev, il est tout à fait possible d'hériter de plusieurs parents (ce n'est pas le cas dans tous les langages). Je vous invite toutefois à éviter d'utiliser les héritages multiples, puisque comme nous ne le verrons pas, cela peut poser des ambiguïtés dans le code.

Pas satisfait de l'héritage ? Redéfinissez le !

Revenons sur la notion d'héritage génétique dont je parlais plus tôt. Dans le cas d'un être humain,
on récupère une partie du génome paternel et une partie du génome maternel. Cette manière de faire garantit à la population humaine une quasi unicité de chaque individu.

Par contre, dans le cas de la POO, il faudrait considérer qu'il n'y a qu'un seul parent. 100 % du génome du parent est transmis à l'enfant. Et qu'est-ce que ça donne ? Un clone !

Dans l'exemple précédent, la classe cEnfant est un clone de la classe cParent. Les deux classes font exactement la même chose. Ce qui ne sert pas à grand chose en programmation... C'est pourquoi nous allons voir qu'il est possible de modifier certains des éléments que l'enfant hérite et lui ajouter aussi de nouveaux éléments.

Ajouter des méthodes

La manière la plus simple pour enrichir une classe enfant, c'est en lui créant de nouvelles méthodes. Ces méthodes seront disponibles pour l'enfant, mais pas pour le parent.

Modifier des méthodes

On commence à toucher au polymorphisme.
Imaginons que la classe cParent ait la méthode suivante :

PROCÉDURE qui_es_tu()
RENVOYER "je suis le parent"

Cela n'a pas de sens si on invoque la méthode sur une instance de la classe cEnfant qui répondra elle aussi : je suis le parent.

Pour corriger cela, on va simplement créer une nouvelle méthode dans la classe cEnfant qui porte la même signature que la méthode parente :

PROCÉDURE qui_es_tu()
RENVOYER "je suis l'enfant"

Tout simplement !

Accéder au méthode du parent

Une classe enfant peut toujours invoquer les méthodes du parents, même si celles-ci ont été redéfinies. Cet exemple sera très parlant :

PROCÉDURE qui_es_ton_parent()
RENVOYER "mon parent aurait dit : " + cParent:qui_es_tu()

Pour appeler le constructeur d'un parent, il faut écrire :

PROCÉDURE Constructeur()
Constructeur cParent()

On peut bien entendu passer les paramètres que l'on souhaite au constructeur de cParent.

Un peu de polymorphisme

Avec tous ces éléments, on peut commencer à mettre en place certains éléments du polymorphisme. Imaginons que l'on définisse la méthode suivante dans la classe cParent :

PROCÉDURE présente_toi()
RENVOYER "Je me présente : " + :qui_es_tu()

Mais nous ne redéfinissons pas cette méthode dans la classe cEnfant. Lorsque le parent l'appelle, on obtient : Je me présente : je suis le parent.

A son tour, l'enfant peut bien entendu utiliser cette méthode. Mais quel résultat allons nous avoir ? En effet, nous allons appeler une méthode qui_es_tu, mais laquelle ? Celle de l'enfant bien sûr. Nous obtenons : Je me présente : je suis l'enfant.

Nous venons de modifier le comportement d'une méthode sans la redéfinir, commencez-vous à comprendre l'intérêt de l'héritage ?

Il faut être dynamique pour profiter de l'héritage de ses enfants !

Nous allons enfin aborder le polymorphisme ! Mettons en place l'exemple suivant :

Tout d'abord, la classe cAnimal :

cAnimal est une Classe

PRIVÉ
    __prénom est chaîne
FIN

PROCÉDURE Constructeur(prénom est chaîne)
:__prénom = prénom

PROCÉDURE fais_ton_action()
RENVOYER "je ne fais rien"

PROCÉDURE fais_ton_bruit()
RENVOYER "..."

PROCÉDURE presente_toi()
RENVOYER _([
    Je m'appelle '%1'.
    Je suis un animal de type '%2'.
    Mon bruit ? '%3'.
    Qu'est-ce que je fais ? %4.
    ], :__prénom, :donne_ton_type(), :fais_ton_bruit(), :fais_ton_action())

PROCÉDURE donne_ton_type()
RENVOYER "inconnu"

On crée ensuite une classe cChien :

cChien est une Classe
hérite de cAnimal
FIN

PROCÉDURE Constructeur(prenom est chaîne)
Constructeur cAnimal(prenom)

PROCÉDURE donne_ton_type()
RENVOYER "chien"

PROCÉDURE fais_ton_action()
RENVOYER "j'aboie et je creuse des trous"

PROCÉDURE fais_ton_bruit()
RENVOYER :aboies()

PROCÉDURE aboies()
RENVOYER "ouaf ouaf"

En enfin la classe cChat :

cChat est une Classe
hérite de cAnimal
FIN

PROCÉDURE Constructeur(prenom est chaîne)
Constructeur cAnimal(prenom)

PROCÉDURE donne_ton_type()
RENVOYER "chat"

PROCÉDURE fais_ton_action()
RENVOYER "je miaule et je chasse les souris"

PROCÉDURE fais_ton_bruit()
RENVOYER :miauler()

PROCÉDURE miauler()
RENVOYER "miaou miaou"

Et un code pour tester tout cela (mettez le dans le bouton d'une fenêtre):

animaux est un tableau de cAnimal dynamique = [allouer un cAnimal("Denver"), allouer un cChien("PIF"), allouer un cChat("HERCULE")]
un_animal est un cAnimal("")

POUR i = 1 _À_ animaux..Occurrence
    un_animal = animaux[i]
    Trace("presente_toi :", un_animal.presente_toi())
    Trace("")
FIN

Pour le dernier code, j'aurai pu faire un POUR TOUT, mais j'ai préféré faire une simple boucle pour mettre en évidence la notion de polymorphisme.

Tout d'abord, testez ce code et voyez ce que ça fait. On obtient la trace suivante :

presente_toi : Je m'appelle 'Denver'.
Je suis un animal de type 'inconnu'.
Mon bruit ? '...'.
Qu'est-ce que je fais ? je ne fais rien.

presente_toi : Je m'appelle 'PIF'.
Je suis un animal de type 'inconnu'.
Mon bruit ? '...'.
Qu'est-ce que je fais ? je ne fais rien.

presente_toi : Je m'appelle 'HERCULE'.
Je suis un animal de type 'inconnu'.
Mon bruit ? '...'.
Qu'est-ce que je fais ? je ne fais rien.

Ensuite, remplacez la ligne un_animal est un cAnimal("") par un_animal est un cAnimal dynamique et exécutez à nouveau le code. On obtient cette trace :

presente_toi : Je m'appelle 'Denver'.
Je suis un animal de type 'inconnu'.
Mon bruit ? '...'.
Qu'est-ce que je fais ? je ne fais rien.

presente_toi : Je m'appelle 'PIF'.
Je suis un animal de type 'chien'.
Mon bruit ? 'ouaf ouaf'.
Qu'est-ce que je fais ? j'aboie et je creuse des trous.

presente_toi : Je m'appelle 'HERCULE'.
Je suis un animal de type 'chat'.
Mon bruit ? 'miaou miaou'.
Qu'est-ce que je fais ? je miaule et je chasse les souris.

Constatez-vous la différence ? Dans les deux exemples, on manipule des instances issues de cAnimal, cChien et cChat. Le résultat du premier exemple montre cependant que l'on considère chaque instance manipulée comme si elle était issue de la classe cAnimal. On a un seul comportement.

Le deuxième résultat montre par contre une évolution du comportement et bien qu'on utilise seulement une variable de type cAnimal dynamique pour parcourir le tableau, on obtient le comportent d'un cAnimal, puis d'un cChien et enfin d'un cChat. Voilà ce qu'est le polymorphisme !

Pourquoi cette différence ? Parce que l'on a utilisé le mot clé dynamique. Je vais éviter de rentrer dans le détail du pourquoi et du comment. C'est ce mot clé qui permet de mettre en œuvre le polymorphisme dans WinDev (du moins jusqu'à la version 22, car les interfaces apparues en 23 permettent aussi d'utiliser le polymorphisme, mais nous verrons cela une prochaine fois).

Ce mot clé dynamique est accompagné des deux mots clés Allouer et Libérer. Le premier permet de créer une instance de classe (on appelle le constructeur) tandis que le second permet de libérer cette instance (et donc on appelle le destructeur). Je ne libère pas souvent les instances car WinDev s'en occupe lui même (de manière générale) mais j'use et j'abuse des mots clés dynamique et allouer.

Conclusion

Voilà, nous avons vu comment mettre en place l'héritage de classe dans WinDev avec le mot clé hérite. L'objectif de l'héritage est d'enrichir ou modifier le comportement de la classe enfant, pour cela, vous pourrez utiliser la redéfinition des classes. Et enfin, un des éléments clés de la POO, le polymorphisme avec le mot clé dynamique.

Vous commencez maintenant à en savoir assez pour commencer à mettre en place de véritables applications basées sur la POO. Mais la route est encore longue ! J'ai encore plein de notions à vous apprendre, comme par exemple, les interfaces et les classes abstraites, mais aussi des petits détails (qui sont tout de même importants) comme la portée des méthodes et des membres. Je crois que je pourrais écrire un livre complet avec tout ce qu'il vous reste à découvrir. Moi-même, j'en apprends tous les jours.

J'espère que cet article vous a plu. N'hésitez pas à laisser votre avis en commentaire, que ce soit pour corriger une erreur, apporter des précisions ou pour poser des questions. N'hésitez pas non plus à partager cet article avec vos collègues et / ou sur les réseaux sociaux. Cela m'aidera à me faire connaître et m'apportera beaucoup de motivation.

Enfin, sachez que vous pouvez aider mon blog. Pour cela, vous pouvez participer à la vie du blog en m'indiquant ce qui vous intéresse. Vous pouvez aussi visiter la boutique. Enfin, si vous souhaitez un accompagnement plus poussé, je peux aussi devenir votre coach en W-Langage.

Je vous remercie pour votre lecture et j'espère que vous aurez pris autant de plaisir à le lire que moi à l'écrire.

A très bientôt !