1 / 95

Chapitre V

Chapitre V. Héritage ou dérivation d’une classe. Héritage. Permet de créer une classe à partir d’une autre i.e. la nouvelle classe bénéficie des données et fonctions membres de la classe dont elle dérive. Dans cette nouvelle classe, vous pourrez ensuite définir de nouveaux membres afin

diamond
Télécharger la présentation

Chapitre V

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapitre V Héritage ou dérivation d’une classe

  2. Héritage Permet de créer une classe à partir d’une autre i.e. la nouvelle classe bénéficie des données et fonctions membres de la classe dont elle dérive. Dans cette nouvelle classe, vous pourrez ensuite définir de nouveaux membres afin de modifier et spécialiser la classe de base. Avantages de l’héritage : • Technique permettant de réutiliser et de spécialiser les classes existantes : • évite de réécrire du code lorsqu’un comportement est hérité d’une autre classe; • - augmente la fiabilité du code et réduit les coûts de maintenance. • Partage du code : • plusieurs programmeurs ou projets peuvent utiliser les mêmes classes; • plusieurs classes développées dans un projet peuvent hériter d’une même classe; • ainsi, plusieurs types d’objets partagent le code qu’ils héritent; ce code est écrit • une seule fois.

  3. Héritage Avantages de l’héritage : • Consistance des interfaces : • lorsque plusieurs classes héritent de la même super-classe, celles-ci auront les • les mêmes comportements; • l’héritage permet d’unifier différents types d’objets sur la base de leurs • ressemblances. • Prototypage rapide : • lorsqu’on construit un système à partir de composantes réutilisables, on investit • le temps de développement dans les nouvelles zones moins connues du logiciel; • permet de générer plus rapidement des prototypes de notre système. • Masquage d’information : • réduction du couplage des données; • on se concentre sur la compréhension de la nature des abstractions disponibles • et de leur interface; • la compréhension des mécanismes d’implantation n’est pas nécessaire à la bonne • utilisation de ces composantes.

  4. Héritage Coûts de l’héritage : • Rapidité d’exécution • on ne peut espérer obtenir autant de performance avec des outils génériques • qu’avec une implantation spécifique. • toutefois, la perte de performance est mineure et est compensée par une • augmentation de la rapidité de développement. • Dimension du code exécutable • l’utilisation de librairies réutilisables produit souvent des exécutables plus gros • que les systèmes conçus spécifiquement pour un projet. • toutefois, contenir les coûts, produire de la qualité et du code exempt d’erreur • est plus important. • Appel de méthode • il y a un coût à payer pour un appel de méthode p/r à un appel de procédure. • toutefois, il y a un gain à utiliser la technologie OO. • Complexité du programme • la sur-utilisation de l’héritage augmente la complexité.

  5. Réutilisation Utiliser du code existant plutôt que de réécrire chaque application à partir de rien. Accélère le temps de développement. Réduit le coût de l’écriture et de la maintenance du code d’une application. Réutilisation par « recyclage » Prendre un bout de code dans un programme qui nous intéresse et l’utiliser dans un autre programme en l’adaptant. Souvent plus facile de tout réécrire… Problèmes rencontrés : Trouver le code qui nous intéresse peut être difficile. Pas d’assurance que le code provenant d’un autre programme est correct. Il peut être difficile de détacher un bout de code d’un programme à cause des nombreuses dépendances qui y sont implantées. Le bout de code extrait peut demander d’importantes modifications pour fonctionner dans le nouveau programme.

  6. Propriétés essentielles du code réutilisable Facile à trouver et à comprendre. Assurance raisonnable que le code est correct. Ne demande pas d’effectuer une séparation du code qui le contient. Ne demande pas de changement pour être utilisé dans un nouveau programme. Mythes de la réutilisation La réutilisation résoudra la crise du logiciel. Tout le code qu’on écrit devrait être réutilisable. Il est toujours préférable de réutiliser que de coder à partir de rien. La programmation orientée objet rend facile l’écriture de code réutilisable.

  7. Illustration du concept d’héritage Je connais bon nombre de comportements de Gilles, le fournisseur de bois, non pas parce que je sais qu’il est fournisseur de bois, mais parce qu’il est un commerçant. De ce fait, je m’attends à ce qu’il me demande de l’argent pour ses services et qu’il me donne un reçu en échange. Ces comportements sont aussi vrais pour l’épicier, le fleuriste ou le coiffeur. Étant donné que fournisseur de bois est plus spécialisé que Commerçant, ce qui est vrai pour le commerçant est vrai pour le fournisseur de bois et donc pour Gilles. En structurant nos connaissances du problème à résoudre de manière hiérarchique, cela permet une meilleure compréhension du problème.

  8. Illustration du concept d’héritage Citoyen Commerçant Fournisseur de bois

  9. Illustration du concept d’héritage Prêt Prêt auto Prêt hypothécaire Prêt rénovations Compte Forme Compte d’épargne Compte chèque Cercle Triangle Rectangle

  10. Hiérarchie d’héritage pour les membres d’une communauté universitaire Membre Communauté Employé Étudiant Ancien Employé en faculté Personnel hors faculté Étudiant employé Héritage multiple Administrateur Enseignant Administrateur Enseignant Héritage multiple

  11. Types d’héritage (Yves Roy) Spécialisation Spécification Forme classique d’héritage Hériter pour spécialiser Construction Généralisation Extension Matrice Limitation Codes communs Matrice carrée

  12. Types d’héritage (Yves Roy) Spécialisation Réalisation d’une spécification abstraite S’assurer que les héritiers auront une même interface Le parent est désigné comme classe abstraite parce qu’il définit des comportements communs sans les implanter, les héritiers le feront. Spécification Construction Généralisation Extension Figure géométrique Limitation Codes communs • Opérations imposées aux • figures géométriques : • Afficher - Aire • - Normale - etc. Polygone Cercle

  13. Types d’héritage (Yves Roy) Spécialisation Héritage utilitaire On veut récupérer diverses fonctionnalités du parent tout en modifiant certains paramètres ou nom de méthode. Approche à éviter : utiliser l’agrégation à la place. Spécification Construction Généralisation Extension Liste simple Limitation Une pile n’est pas une liste à laquelle on ajoute des méthodes spécifiques à la pile. La liste peut être utilisée comme attribut de la classe Pile. Codes communs Pile

  14. Types d’héritage (Yves Roy) Spécialisation Inverse de la spécialisation Une sous-classe va créer un concept plus général que son parent en modifiant ou élargissant sa gamme de comportements. Fréquent lorsqu’on bâtit sur des classes existantes dont on ne peut pas modifier le contenu. Approche à éviter : préférable d’utiliser la spécialisation. Spécification Construction Généralisation Extension Limitation Codes communs

  15. Types d’héritage (Yves Roy) Spécialisation Figure géométrique Spécification Librairie on ne possède pas le code source Construction Généralisation Polygone Cercle Extension Limitation Généralisation Renferme des fonctionnalités supplémentaires Codes communs Polygone+ Cercle+

  16. Types d’héritage (Yves Roy) Spécialisation Héritage pour restreindre le comportement d’une sous-classe p/r au parent. Fréquent lorsqu’on bâtit sur des classes existantes dont on ne peut pas modifier le contenu. Approche à éviter. Spécification Construction Généralisation Extension Dèque Limitation Les opérations possibles sur une pile sont limitées p/r à celles d’un dèque. Il faut redéfinir les méthodes trop permissives. Codes communs Pile Chapitre V - Héritage ou dérivation d'une classe

  17. Types d’héritage (Yves Roy) Spécialisation Des classes possèdent un code commun mais n’ont pas de lien hiérarchique. On choisit arbitrairement une des classes comme parent laquelle renfermera le code commun. Fréquent lorsqu’on bâtit sur des classes existantes dont on ne peut pas modifier le contenu. Approche à éviter : Préférable de factoriser le code commun dans une classe abstraite. Spécification Construction Généralisation Extension Limitation Codes communs Chapitre V - Héritage ou dérivation d'une classe

  18. Types d’héritage (Yves Roy) Spécialisation Il existe un code commun aux 2 classes. Il n’y a aucune raison pourquoi la tablette graphique hériterait de la souris. Souris Spécification Construction Tablette graphique Généralisation Extension Périphérique d’entrée Classe abstraite Limitation Codes communs Tablette graphique Souris Les héritiers implantent leur code spécifique. Chapitre V - Héritage ou dérivation d'une classe

  19. Héritage en C++ La classe dont dérive une classe se nomme la classe de base, la superclasse, la classe parent, la classe ancêtre, la classe mère ou la classe père. La classe dérivée se nomme la classe fille ou la sous-classe. Chaque fois que vous créez un objet d ’une classe dérivée, C++ créera un objet de la classe de base. Par ex., si B dérive de A, un objet de B est un objet de A avec des éléments supplém. Les données membres des classes de base sont créées pour chaque objet dérivé indépendamment des directives de protection. Exemple : Si B dérive de A, et qu’une donnée membre de A est définie en privée (private), elle est allouée quand même. Elle sera utilisable par la partie A de l ’objet B et non par les méthodes spécifiques de B. Chapitre V - Héritage ou dérivation d'une classe

  20. Héritage Ce processus de création automatique d’un objet de la classe de base, chaque fois que l’on déclare un objet de la classe dérivée, se propage tout au long de la hiérarchie. Bien distinguer entre l’utilisation de classes indépendantes et l’héritage. Mise en oeuvre class Nom_de_la_classe_derivee : <acces> Nom_de_la_classe_de_base { ….. }; <acces> désigne l ’une des 3 valeurs suivantes: public, private et protected. à venir Chapitre V - Héritage ou dérivation d'une classe

  21. Héritage Exemple : une classe B qui dérive de la classe A. class B : public A { …… }; Note : La classe A doit obligatoirement être déclarée avant la classe B. Chapitre V - Héritage ou dérivation d'une classe

  22. Héritage Exemple Liste_simple Exercices résolus (chap. IV) Polygone_2D « hérite de » Polygone_2D_convexe Chapitre V - Héritage ou dérivation d'une classe

  23. Polygone_2D.h #include "Liste_simple.h" struct sommet_2D { int x, y; }; class Polygone_2D { /* Spécification fonctionnelle de la classe " Polygone_2D " Composantes : Chaque composante est un sommet du polygone 2D. Structure : Il existe une relation linéaire (structure) entre les sommets du polygone. Cette relation décrit le mode de parcours du contour polygonal dans le sens horaire. */ Chapitre V - Héritage ou dérivation d'une classe

  24. Polygone_2D.h (suite) protected: int Nb_de_sommets; /* Nombre de sommets du polygone */ Liste_simple Ensemble_des_sommets; float Aire_Triangle_2D(int x, int y, int u, int v, int a, int b); /* Retourne l'aire du triangle dont les coordonnées des sommets sont resp. (x, y), (u, v) et (a, b). Pré - Nil Post - Retourne l'aire du triangle 2D. */ Chapitre V - Héritage ou dérivation d'une classe

  25. Polygone_2D.h (suite) public: Polygone_2D(); /* Permet de créer un polygone 2D à 0 sommet. Pré - L > 0. Post - Un polygone à 0 sommet est créé. */ void Ajouter_sommet(int x, int y); /* Permet d'ajouter un sommet de coordonnées x, y au polygone. L'ordre d'insertion des sommets du polygone doit respecter un mode de parcours dans le sens horaire. Pré - Le polygone 2D a déjà été créé. Post - Un sommet de coordonnées x,y a été ajouté au polygone.*/ Chapitre V - Héritage ou dérivation d'une classe

  26. Polygone_2D.h (suite) int Nombre_de_sommets(); /* Retourne le nombre de sommets du polygone 2D. Pré - Le polygone 2D a déjà été créé. Post - Retourne le nombre de sommets. */ void Detruire_Polygone_2D(); /* Permet de détruire les sommets du polygone 2D. Pré - Le polygone 2D a déjà été créé et renferme au moins un sommet. Post - Les sommets du polygone 2D ont été détruits. Le polygone renferme 0 sommet. */ Chapitre V - Héritage ou dérivation d'une classe

  27. Polygone_2D.h (fin) float Aire_Polygone_2D(); /* Retourne l'aire du polygone 2D. Pré - Le polygone 2D a déjà été créé et le nombre de sommets est supérieur ou égal à 3. Post - L'aire du polygone 2D est retourné. */ }; Chapitre V - Héritage ou dérivation d'une classe

  28. Polygone_2D.cpp #include <iostream.h> #include "Polygone_2D.h" Polygone_2D::Polygone_2D() { Nb_de_sommets = 0; } void Polygone_2D::Ajouter_sommet(int x, int y) { sommet_2D * P = new sommet_2D; (*P).x = x; (*P).y = y; Ensemble_des_sommets.Inserer_fin_liste(P); Nb_de_sommets = Nb_de_sommets + 1; } Chapitre V - Héritage ou dérivation d'une classe

  29. Polygone_2D.cpp (suite) int Polygone_2D::Nombre_de_sommets() { return Nb_de_sommets; } void Polygone_2D::Detruire_Polygone_2D() { Ensemble_des_sommets.Detruire_liste(); Nb_de_sommets = 0; } Chapitre V - Héritage ou dérivation d'une classe

  30. Polygone_2D.cpp (suite) float Polygone_2D::Aire_Triangle_2D(int x, int y, int u, int v, int a, int b) { float aire; aire = ((float) ((v - y)*(a - x) - (u - x)*(b-y))) / 2.0f; return aire; } Chapitre V - Héritage ou dérivation d'une classe

  31. Polygone_2D.cpp (suite) float Polygone_2D::Aire_Polygone_2D() { int x, y, u, v, a, b; bool Fin; struct sommet_2D * P; float somme = 0.0; Ensemble_des_sommets.Positionner_debut_liste(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); x = (*P).x; y = (*P).y; Chapitre V - Héritage ou dérivation d'une classe

  32. Polygone_2D.cpp (suite) Fin = Ensemble_des_sommets.Positionner_sommet_suivant(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); u = (*P).x; v = (*P).y; Fin = Ensemble_des_sommets.Positionner_sommet_suivant(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); a = (*P).x; b = (*P).y; somme = somme + Aire_Triangle_2D(x, y, u, v, a, b); Chapitre V - Héritage ou dérivation d'une classe

  33. Polygone_2D.cpp (fin) while (Ensemble_des_sommets.Positionner_sommet_suivant() == false) { P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); u = a; v = b; a = (*P).x; b = (*P).y; somme = somme + Aire_Triangle_2D(x, y, u, v, a, b); } return somme; } Chapitre V - Héritage ou dérivation d'une classe

  34. Application Polygone_2D.cpp #include <iostream.h> #include "Polygone_2D.h" void main() { Polygone_2D Q; Q.Ajouter_sommet(1, 1); Q.Ajouter_sommet(1, 3); Q.Ajouter_sommet(2, 3); Q.Ajouter_sommet(2, 2); Q.Ajouter_sommet(3, 2); Q.Ajouter_sommet(3, 3); Q.Ajouter_sommet(4, 3); Q.Ajouter_sommet(4, 1); cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); cout << "Aire du polygone 2D : " << Q.Aire_Polygone_2D(); Q.Detruire_Polygone_2D(); cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); } Chapitre V - Héritage ou dérivation d'une classe

  35. Héritage Exemple (suite) Liste_simple Exercices résolus (chap. IV) Polygone_2D « hérite de » Polygone_2D_convexe Chapitre V - Héritage ou dérivation d'une classe

  36. Polygone_2D_convexe.h #include "Polygone_2D.h" class Polygone_2D_convexe : publicPolygone_2D { /* Spécification fonctionnelle de la classe " Polygone_2D_convexe " dérivée de la classe "Polygone_2D". Composantes :Chaque composante est un sommet d'un polygone convexe Structure : Il existe une relation linéaire (structure) entre les sommets du polygone. Cette relation décrit le mode de parcours du contour polygonal dans le sens horaire. */ Chapitre V - Héritage ou dérivation d'une classe

  37. Polygone_2D_convexe.h public: void Point_visible_Polygone_2D_convexe(float * x, float * y); /* Permet de calculer un point intérieur au polygone lequel est visible de tous ses sommets. Pré - Le polygone 2D convexe a déjà été créé et le nombre de sommets est supérieur ou égal à 3. Post - Les coordonnées réelles x, y d'un point visible du polygone 2D convexe sont retournées en paramètres. */ }; Chapitre V - Héritage ou dérivation d'une classe

  38. Polygone_2D_convexe.cpp #include <iostream.h> #include "Polygone_2D_convexe.h" void Polygone_2D_convexe::Point_visible_Polygone_2D_convexe (float * x, float * y) { float Vx, Vy; struct sommet_2D * P; Ensemble_des_sommets.Positionner_debut_liste(); P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); Vx = (*P).x / (float) Nb_de_sommets; Vy = (*P).y / (float) Nb_de_sommets; Chapitre V - Héritage ou dérivation d'une classe

  39. Polygone_2D_convexe.cpp while (Ensemble_des_sommets.Positionner_sommet_suivant() == false) { P = (sommet_2D *) Ensemble_des_sommets.Acces_element_courant(); Vx = Vx + (*P).x / (float) Nb_de_sommets; Vy = Vy + (*P).y / (float) Nb_de_sommets; } *x = Vx; *y = Vy; } Chapitre V - Héritage ou dérivation d'une classe

  40. Application Polygone_2D_convexe.cpp #include <iostream.h> #include "Polygone_2D_convexe.h" void main() { float a, b; Polygone_2D_convexe Q; Q.Ajouter_sommet(1, 1); Q.Ajouter_sommet(1, 3); Q.Ajouter_sommet(4, 3); Q.Ajouter_sommet(4, 1); Chapitre V - Héritage ou dérivation d'une classe

  41. Application Polygone_2D_convexe.cpp cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); cout << "Aire du polygone 2D : " << Q.Aire_Polygone_2D(); Q.Point_visible_Polygone_2D_convexe(&a, &b); cout << "Point visible : " << a << " , " << b; Q.Detruire_Polygone_2D(); cout << "Nombre de sommets : " << Q.Nombre_de_sommets(); } Chapitre V - Héritage ou dérivation d'une classe

  42. Héritage et protection des membres Rappel: 3 étiquettes de protection : public, privateetprotected. Une classe dérivée peut accéder aux données membres publiques et protégées de la classe de base. Les données privées ne sont manipulables que par les fonctions membres public et protected de la classe qui les a définies. Principe : • Mieux vaut laisser privées toutes les données car, • n’importe quelle fonction membre de classe dérivée peut corrompre • les données protégées de la classe de base. • les classes possédant des données membres protégées sont difficiles • à modifier car quelqu’un peut avoir écrit une classe dérivée dont le • code repose sur ces données membres protégées. Chapitre V - Héritage ou dérivation d'une classe

  43. Héritage et protection des membres Exemple: class A { public: int i; protected: int j; private: int z; public: A(); void Affiche(); }; class B : public A { public : void Utilise(); }; A::A() { i=1; j=2; z=3; } Chapitre V - Héritage ou dérivation d'une classe

  44. Héritage et protection des membres Exemple: (suite) void main() { B b; b.Utilise(); // b.i = 7;// possible, car i est // public. // b.Affiche(); // possible. } void A::Affiche() { cout << "i : "   << i << " \n  "; cout <<   "j : "   << j << " \n  "; cout <<   "z : "   << z << " \n  "; } void B:: Utilise() { i=4; j=5; // z=6; // impossible, car z est privée. Affiche(); } i : 4 j : 5 z : 3 public Chapitre V - Héritage ou dérivation d'une classe

  45. Héritage et protection des membres Note: La donnée membre i et la fonction Affiche() sont accessibles par toute fonction qui déclare un objet de ce type ou d ’un type dérivé. Quelles que soient les étiquettes de protection, une fonction membre d’une classe peut accéder à toutes les données membres de cette classe. Un constructeur, comme toute fonction membre, doit être intégré à une étiquette de protection. Dans la plupart des cas, les constructeurs sont déclarés dans la section public, ce qui permet à quiconque de créer les objets de cette classe en utilisant ces constructeurs. Chapitre V - Héritage ou dérivation d'une classe

  46. Spécification de l’héritage En dérivant une classe, nous devons indiquer l ’étiquette de protection: class B : public A // Autres choix : private et protected { ….. }; Permet de spécifier la façon dont se propagera l’héritage en termes d ’accès dans une hiérarchie de classes. Dans la pratique, vous utiliserez presque exclusivement l’étiquette public. 2 règles d ’utilisation: Si vous omettez d ’employer un de ces mots clés, l’étiquette private est la valeur par défaut. Le choix de l’étiquette ne change rien pour la classe dérivée (B dans l’exemple) La spécification d’héritage n ’interviendra que pour les classes dérivées de B. Chapitre V - Héritage ou dérivation d'une classe

  47. Spécification de l’héritage Nous pouvons donc préciser pour une classe, la politique d’accès de ses propres classes dérivées. Si B dérive de A avec le mot clé: La protection des membres de la classe A reste inchangée au niveau de B. On peut imaginer chaque objet de la classe dérivée comme un objet de la classe de base. public: protected: Les membres public et protected de A sont considérés comme protected dans la classe B. Dans ce cas, les classes dérivées de B ont toujours accès aux membres de A. private: Les membres public et protected de A sont considérés comme private dans la classe B. Les fonctions deviennent des utilitaires. Les classes dérivées de B n’ont plus accès aux membres de A. Forme alternative de la composition (voir ultérieurement).

  48. Sommaire de l’accessibilité des membres de la classe de base dans une classe dérivée Mode d’accès aux membres de la classe de base Héritage protected Héritage private Héritage public public dans la classe dérivée. Accessible directement à partir de toute fonction membre, friend ou non membre. protected dans la classe dérivée. Accessible directement à partir de toute fonc- tion membre ou friend. private dans la classe dérivée. Accessible directe- ment à partir de toute fonction membre ou friend. public protected dans la classe dérivée. Accessible directement à partir de toute fonction membre ou friend. protected dans la classe dérivée. Accessible directement à partir de toute fonc- tion membre ou friend. private dans la classe dérivée. Accessible directe- ment à partir de toute fonction membre ou friend. protected

  49. Sommaire de l’accessibilité des membres de la classe de base dans une classe dérivée Mode d’accès aux membres de la classe de base Héritage protected Héritage private Héritage public masqué dans la classe dérivée. Accessible directement à partir de toute fonction membre ou friend par le biais des fonctions membres public ou protected de la classe de base. masqué dans la classe dérivée. Accessible directement à partir de toute fonc- tion membre ou friend par le biais des fonctions membres public ou protected de la classe de base. masqué dans la classe dérivée. Accessible directe- ment à partir de toute fonction membre ou friend par le biais des fonctions membres public ou protected de la classe de base. private

  50. Spécification de l’héritage L’étiquette de protection private utilisée par la classe de base ne peut pas être modifiée par les classes dérivées. Par l’héritage, vous ne pouvez qu’augmenter le niveau de sécurité, jamais le diminuer. Dans la pratique, les 2 spécifications d’héritage protected et private sont rarement utilisées puisqu’elles ont tendance à couper la relation d’héritage. Chapitre V - Héritage ou dérivation d'une classe

More Related