Rappelons qu'il est possible de redéfinir une opération dans des classes héritant d'une classe de base. Il est alors possible d'appeler la méthode d'un objet sans se soucier de son type intrinsèque : il s'agit du polymorphisme1 d'héritage. Ceci permet de faire abstraction des détails des classes spécialisées d'une famille d'objet, en les masquant par une interface commune (qui est la classe de base).
Polymorphisme et classe abstraite
Dans cet exemple, les classes employé, mensuel et journalier peuvent avoir chacune une fonction "calcul_paye()". Cela permettra de ne pas avoir à se soucier du type de l'objet que l'on a si on souhaite calculer
le salaire de l'employé. De telles fonctions sont appelées fonctions virtuelles.
En C++, la déclaration de la fonction doit être précédée du mot clé "virtual", par exemple l'opération calcule-paye() se déclare :
virtual void calcul_paye();
Le polymorphisme peut se présenter sous d'autres formes, par exemple le polymorphisme paramétrique. Il est aussi appelé généricité2, il représente la possibilité de définir plusieurs fonctions de même nom mais possédant des paramètres différents (en nombre et/ou en type). Le polymorphisme paramétrique rend ainsi possible le choix automatique de la bonne méthode à adopter en
fonction du type de donnée passée en paramètre.
Ainsi, on peut par exemple définir plusieurs méthodes homonymes addition() effectuant une somme de valeurs :
- La méthode int addition(int, int) pourra retourner la somme de deux entiers.
- La méthode float addition(float, float) pourra retourner la somme de deux flottants.
- La méthode char addition(char, char) pourra définir au gré de l'auteur la somme de deux caractères.
- etc.
La classe abstraite
On utilise des relations de généralisation pour modéliser un graphe de classes (avec des abstractions plus générales en haut de la hiérarchie et plus spécifiques en bas). A l'intérieur de ces hiérarchies, on précise habituellement que certaines sont abstraites, ce qui signifie qu'elles peuvent n'avoir aucune instance directe (le nom de la classe est alors mis en italique).
Les classes concrètes quand à elles peuvent avoir des instances directes comme par exemple la classe cercle.
Classes abstraites et classes concrètes
Reprenons l'exemple de la classe Employé : on peut décider d'en faire une classe abstraite ainsi
les deux classes filles Mensuel et Journalier seront les classes concrètes associées. En C++,
les classes abstraites correspondent à des classes qui contiennent au moins une fonction virtuelle pure.
Une fonction virtuelle pure doit être obligatoirement redéfinie dans les classes filles, elles se reconnaîssent
par leur initialisation à zéro lors de leur déclaration.
Si on transforme la méthode calcul_paye() en une méthode virtuelle pure, elle s'écrirait en C++ :
virtual void calcul_paye()=0;
Ceci a pour conséquence de ne plus autoriser l'instanciation de la classe Employé, en d'autres mots on ne peut créer que des objets de type Mensuel ou Journalier et non de type Employé.
Polymorphisme1 : concept de la théorie des types, selon lequel un nom peut référencer des objets instances de plusieurs classes regroupées dans une hierarchie de généralisation (opposé à monomorphisme).
Généricité2 : le fait pour un objet de pouvoir être utilisé tel quel dans différents contextes (ou même indépendamment du contexte).