4.2.12 Méthode Polymorphique et liaison
dynamique
- Méthode polymorphique :
- Un objet d’une classe enfant peut prendre plusieurs
formes
- L’objet peut être utilisé partout où un objet de la
classe parente est attendu
- Exprimant que la classe enfant est une spécialisation de la
classe parente
- P.ex., void o(MoyenTransport
r) accepte o(e) avec e de type Tramway
- Liaison dynamique ou tardive :
- Soient une classe P et
o() une opération
de P
- Soient e un objet d’une
classe E, enfant de la classe P
et o()
l’opération redéfinie dans E
- Soit r une référence sur un
objet de type P
- Le polymorphisme autorise à affecter à r la valeur e : r ← e
- Si l’opération o() est appelée sur la
référence r : r.o()
et s’il y a liaison dynamique (ce qui est toujours le cas en Java p.ex.)
- C’est l’opération redéfinie dans la classe
enfant qui est appelée
soit l’opération o() redéfinie dans E
précédent suivant
Le prototype d’une méthode contient des déclarations de
types primitifs et de références sur des objets. Ces types sont dits les types
formels de la méthode. Lors de l’exécution, les types des objets passés
en argument de la méthode sont appelés les types effectifs. Lorsqu’une
référence d’une classe est attendue, une référence sur un objet
d’une classe enfant peut être donnée. C’est le principe du
polymorphisme des méthodes. La relation entre le type formel et le type
effectif est donc contrainte par la relation de généralisation spécialisation.
Cette substitution de type est possible lors de l’exécution puisque par
définition l’objet de la classe spécialisée fait tout ce que la classe
parente fait, plus des choses supplémentaires. Si cette classe spécialisée a
redéfini (spécialisé) le comportement d’une opération de la classe
parente, nous souhaitons que ce soit le comportement spécialisé qui soit
utilisé à la place du comportement de la classe parente. C’est ce que
permet la liaison dynamique, aussi appelée liaison tardive.
Prenons un autre exemple avec le diagramme de classes
suivant.
Écrivons une opération acheterMaison() avec la définition suivante.
void acheterMaison(Personne acheteur) {
...
acheteur.changerAdresse();
...
}
Les instructions suivantes sont toutes valides (la
compilation et l’exécution ne violent pas le système de type du langage
orienté objet) avec les déclarations correspondantes. En effet, tout objet
d’une classe enfant peut être utilisé là où un objet de la classe parente
est attendu. En outre, l’opération effectivement appelée / exécutée pour
l’objet jean est celle définie dans la
classe Personne car jean est une instance de cette classe. Pour l’objet
pierre, c’est celle définie dans la
classe enfant Avocat qui est utilisée car
l’opération est redéfinie dans la classe enfant Avocat. Enfin, pour l’objet paul, l’opération choisie à l’exécution est,
selon la règle de « la définition de la classe la plus spécialisée »,
celle de la classe Enseignant.
Personne jean; Avocat pierre; Vacataire paul;
acheterMaison(jean); // licite car jean est une Personne
acheterMaison(pierre); // licite car pierre est d’une classe enfant de Personne
acheterMaison(paul); // licite car paul est d’une classe enfant de Personne
D. Conan, C. Taconet, C. Bac,
Télécom SudParis, CSC 4002, Octobre 2015
|