Modifier

Introduction

Voici enfin la cinquième partie de la programmation orientée objet. Pour ceux qui n'ont pas lu les parties précédentes, vous pourrez les trouver sur cette page.

Dans cette partie, nous allons étudier les classes abstraites et les interfaces. Ce sont de puissants outils qui permettent de simplifier la vie du développeur. En effet, le compilateur les utilise pour vous prévenir lorsqu'où vous oubliez certaines choses dans votre code.

Les classes abstraites sont apparues dans WinDev® 22 et les interfaces dans la version 23.

Les concepts sont assez proches, mais on ne s'en sert pas de la même manière.

Les classes abstraites

Les classes abstraites utilisent le principe de l'héritage et permettent de spécialiser une classe mère à l'aide de ses enfants. La classe mère décrit les principaux comportements attendus et les classes filles décrivent les spécificités.

Lorsqu'on crée une classe abstraite (la classe mère), on indique à l'aide du mot clé Abstrait les méthodes qui doivent être définies dans les classes filles. Ces méthodes abstraites n'auront aucun code dans la classe mère (seulement une signature) et ce sont les classes filles qui implémenteront le code manquant.

Il n'est pas possible d'instancier une classe abstraite. Il faut impérativement instancier une de ses classes filles qui ont elle-même implémenté toutes les méthodes abstraites. Bien entendu, les propriétés peuvent aussi être abstraite.

A l'utilisation, les classes abstraites s'utilisent comme des classes classiques.

Exemple de classe abstraite

Nous définissons une classe cEtreVivant :

cEtreVivant est une classe

Fin

Procédure respirer() // les mammifères et les poissons respirent
    :inspirer() 
    :expirer()
FIN

// mais ils ne récupèrent pas l'oxygène de la même manière
Procédure abstraite inspirer()

// mais ils n'évacuent pas l'oxygène de la même manière
Procédure abstraite expirer()

Une classe cMammifère :

cMammifère est une classe
    herite de cEtreVivant
FIN

Procédure inspirer()
:poumons.remplir()

Procédure expirer()
:poumons.vider()

Et une classe cPoisson :

cPoisson est une classe
    herite de cEtreVivant
FIN

Procédure inspirer()
:branchies.inspirer()

Procédure expirer()
:branchies.expirer()

Les interfaces

Les interfaces permettent de définir un contrat du style : la classe doit savoir faire ceci ou cela. A l'instar de la classe abstraite, l'interface définit des méthodes et des propriétés abstraites. Mais à l'inverse, elle ne définit aucun comportement initial.

Lorsqu'on utilise les interfaces, on ne parle pas d'héritage. On dit qu'une classe implémente une interface, c'est à dire qu'elle respecte le contrat proposé par celle-ci. Mais cette règle n'empêche pas d'utiliser l'héritage.

En règle générale, l'héritage permet d'avoir des classes qui ont une nature proche (un oiseau est un animal par exemple). Mais quand on parle d'interface, les classes qui en découlent peuvent n'avoir aucun lien (si on parle de l'interface PeutVoler, alors, un oiseau et un avion qui sont fondamentalement différents partagent la même interface).

Utilisation

Les interfaces ne s'utilisent pas de la même manière que les classes et classes abstraites.

Définition

Tout d'abord, pour créer une interface, il faut employer une syntaxe qui est assez proche de la définition d'une structure. Cette syntaxe est décrite dans la page d'aide associée de WinDev.

Exemple
ObjetPouvantVoler est une interface
Procédure décoller()
Procédure voler()
Procédure atterir()
Propriété altiltude() : entier
FIN

Implémentation

Lorsqu'on indique qu'une classe implémente une interface, le compilateur vérifie si les propriétés et les méthodes définies par l'interface existent. Si ce n'est pas le cas, une erreur de compilation apparaît. En faisant un clic droit sur ce message d'erreur, le menu contextuel nous donne la possibilité de créer la ou les méthodes manquantes.

Attention, il arrive que la création automatique ne respecte pas le prototype défini dans l'interface. Si on utilise un type structure comme paramètre, l'outil va mettre le mot clé structure au lieu du nom du type. (Souhaitons que ce problème soit corrigé dans les versions supérieures de WinDev).

Dans tous les cas, la première chose à faire lorsqu'on indique que la classe implémente l'interface, c'est d'aller créer les méthodes qui manquent.

Exemple
cAvion est une classe
    hérite de cVéhicule
    implemente ObjetPouvantVoler
Fin

cOiseau est une classe
    hérite de cAnimal
    implemente ObjetPouvantVoler
Fin

Utilisation

Pour utiliser une interface, il faut créer une variable du type de l'interface. On initialise ensuite cette variable depuis une instance d'une classe. Pour cela, il faut utiliser l'opérateur <- (affectation par référence). Si la classe implémente l'interface ou si elle possède les méthodes et propriété définies par l'interface (duck typing), alors la variable pointe vers l'instance. Par contre, si ce n'est pas le cas, la variable contiendra la valeur nulle (ce qui montre l'incompatibilité).

La variable s'utilise ensuite comme une instance de classe traditionnelle mais seule les méthodes et propriétés définies dans l'interface seront disponibles.

Exemple
objet_volant est un ObjetPouvantVoler <- allouer un cAvion()
objet_volant.décoller()
objet_volant.voler()
trace(objet_volant.altitude)
objet_volant.atterir()

Conclusion

Nous avons vu le principe de fonctionnement des interfaces et des classes abstraites ainsi que les manières de les créer. Ces outils sont très pratiques à condition de savoir les utiliser. En effet, ils sont très liés aux notions d'abstraction, de polymorphisme et d'encapsulation que nous avons étudié dans les précédents articles.

Dans le prochain article, nous essaierons de voir dans quel cas utiliser ces notions. Et si vous souhaitez aller plus loin, je vous invite à vous intéresser à mon cours sur la POO (en cours d'écriture). J'essaie d'y aborder les différentes notions au travers d'exercices simples.

N'hésitez pas à me faire vos remarques en commentaire, que ce soit pour poser vos questions ou m'aider à améliorer l'article.

J'espère que cet article vous a intéressé. Merci pour votre lecture.

Article suivant Article précédent

Blog Comments powered by Disqus.