• Aucun résultat trouvé

Les concepts de base de la POO

N/A
N/A
Protected

Academic year: 2022

Partager "Les concepts de base de la POO"

Copied!
10
0
0

Texte intégral

(1)

1

Plan – POO

„

Les concepts de base de la POO

„ Encapsulation / Classe

„ Héritage / Sous-Classes / Classes dérivées

„

Classes abstraites

„

Héritage multiple

„

Polymorphisme

2

Classes abstraites

„ Idée intuitive :

„ Une classe abstraite est une classe dans laquelle on a défini une (ou des méthodes) pour laquelle on a explicitement dit :

„Qu’elle ne sera pas implémentée.

„ L’implémentation de ces méthodes appelées méthodes virtuelles « pures » est laissée à la charge des classes dérivées.

„ On ne peut donc pas instancier des objets de cette classe, mais uniquement des classes dérivées qui auront implémentées ces méthodes virtuelles.

3

Classes abstraites

„

L’objectif d’une classe abstraite est de permettre la définition de profils de méthodes

„

Qui devront être implémentées dans toutes les classes dérivées.

„

Et donc de définir un « comportement » commun à un ensemble de classes dérivées.

4

Classes abstraites

„

Déclaration d’une méthode virtuelle pure :

„

virtual type nom (liste de paramètres) = 0;

„

Si une classe contient une méthode abstraite,

„ aucun objet de cette classe ne peut être manipulé.

„

Nécessité d'employer le mécanisme d'héritage et de spécialisation du descendant

„ pour définir le corps de la méthode

Classes abstraites

„ On considère par exemple la classe CElement qui possède une méthode de dessin qui n’est pas implémentée.

class CElement { …

virtual void Draw() = 0;

};

„ Chaque sous-classe doit spécifier cette implémentation.

„ La déclaration d'un objet de type CElement est incorrecte

„ CElement elem; // déclaration incorrecte

Classes abstraites

„ Description d’une classe dérivée CLine qui implémente la méthode abstraite « Draw »

class CLine : public CElement { ...

public : void Draw();

};

void CLine:: Draw () { // dessin de la ligne }

„ On peut alors déclarer des objets de type CLine

„CLine ligne; // déclaration correcte

(2)

7

Héritage multiple

„ Une classe peut dériver d’une ou plusieurs classes.

„ Supposons que l’on dispose :

„ d’une classe « CEnseignant »,

„ et d’une classe « CChercheur »

„ et l’on souhaite définir une classe dérivée :

« Enseignant_Chercheur »

CChercheur CEnseignant

Enseignant_Chercheur

8

Héritage multiple

„

On peut définir la classe Enseignant_Chercheur à l’aide du mécanisme de d’héritage multiple :

„ class Enseignant_Chercheur : public CEnseignant, public CChercheur

„

La classe Enseignant_Chercheur hérite des attributs et méthodes des classes CEnseignant et CChercheur.

9

Héritage multiple

„ La possibilité de définir des héritages multiples peut conduire à des ambiguïtés:

class CEnseignant { char grade[MAX];

...

public :

void lire_grade(char *); // méthode lire_grade };

class CChercheur { char grade[MAX];

...

public :

void lire_grade(char *); // méthode lire_garde(homonyne) };

class Enseignant_Chercheur : public CEnseignant, public CChercheur { ...};

10

Héritage multiple

„

Existence de méthodes des classes mères (« sur-classes ») qui ont des noms identiques.

„

L’ambiguïté peut être levée en précisant explicitement la classe mère considérée lors de l’appel

„

opérateur de résolution de portée (::)

Héritage multiple

„

Enseignant_Chercheur ec;

„

déclaration d’un “Enseignant_Chercheur”

„

ec.CEnseignant:: lire_grade(mot);

„

mot est le grade de l’enseignant

„

ec.CChercheur:: lire_grade(mot);

„

mot est le grade du chercheur

Héritage multiple

„ Une classe dérivée peut avoir dans ses ascendants plusieurs fois la même classe de base.

„ L’ambiguïté concerne le « partage » de la classe mère.

CChercheur CEnseignant

Enseignant_Chercheur CPersonne

(3)

13

Héritage multiple

„

Y-a-t-il un seul objet de la classe mère ou deux indépendants ?

„Pour obtenir un seul objet de la classe « mère », les classes dérivées « CEnseignant » et « CChercheur » peuvent être définies comme virtuelles :

„

class CEnseignant : public virtual CPersonne

„

class CChercheur : public virtual CPersonne

„lors de la définition de la classe

«Enseignant_Chercheur ».

14

Héritage multiple

„

Le rôle de “virtual” est de signaler au compilateur

„que les classes dérivées de ces classes virtuelles nécessitent un traitement spécial

„suppression des classes ancêtres “en double”

„

Un objet est alors vu comme :

„un unique objet de la classe “CPersonne”

„et les spécificités des classes “CEnseignant” et

“CChercheur”.

15

Polymorphisme

„

Le polymorphisme est un mécanisme puissant,

„ très utile dans la spécification d'une hiérarchie de classes.

„

L'idée intuitive est de permettre l'application d'une "même" opération à des objets différents.

„

La mise en oeuvre de cette propriété est réalisée par deux mécanismes en C++ :

„ la surcharge

„ l'édition de liens dynamique (ligature dynamique)

16

Polymorphisme

„

1 er cas : la surcharge

„

La surcharge offre la possibilité de définir

„

des méthodes homonynes

„(même nom et mêmes paramètres)

„

dans une classe et dans ses classes dérivées.

Polymorphisme

„

2 ème cas : la ligature dynamique

„

Ce mécanisme est encore plus puissant que la surcharge car il permet :

„en cas d'ambiguité sur le choix de la méthode homonyne à utiliser,

„de différer cette décision jusqu'au moment de l'appel de la méthode

„

Génération de tous les codes possibles,

„et décision lorsqu'on connaît la classe de l'objet à traiter

Polymorphisme

„ On considère tout d’abord une classe « CPersonnage ».

„ Un personnage représente un personnage d’un jeu.

„ Tous les personnages ont des caractéristiques communes comme un nom, des points de vie, une position courante, etc.

„ Et on dispose de méthodes pour

„ « dessiner » un personnage,

„ « effacer » un personnage

„ et aussi le « déplacer ».

(4)

19

Polymorphisme

class CPersonnage { protected :

char nom[30];

int posx, poy;

public

CPersonnage(); // construteur

void dessiner(); // méthode qui permet de dessiner à l’écran // le personnage à la position courante posx, poy void effacer(); // pour effacer le personnage à l’écran void deplacer(int, int); // pour effacer le personnage dessiné,

//changer sa position et le redessiner };

20

Polymorphisme

„

On souhaite définir une classe « CMagicien » dérivée de la classe « CPersonnage" .

„

Un magicien est spécialisé par rapport à un personnage par :

„ l'ajout de nouveaux attributs comme les

« sortilèges » qu’il possède …

„ l'ajout/surcharge des méthodes membres et notamment on souhaite pouvoir

„« dessiner », « effacer » et « deplacer » un magicien

21

Polymorphisme

class CMagicien : public CPersonnage { private :

char sortileges[10][30];

… public : CMagicien();

void dessiner () ; void effacer ();

}; ….

22

Polymorphisme

„ Pour dessiner un magicien, on suppose qu’il faut

„d’abord dessiner son personnage

„puis dessiner les caractéristiques spécifiques du magicien (chapeau, cape, …)

void CMagicien :: dessiner () { CPersonnage:: dessiner();

… // dessin des spécificités du magicien }

„ L’appel de la méthode de dessin du personnage est faite l’instruction :

„ CPersonnage ::dessiner();

Polymorphisme

„ De même pour effacer un magicien, on doit d’abord effacer son personnage puis effacer ses caractéristiques spécifiques (chapeau, cape, …)

void CMagicien :: effacer () {CPersonnage:: effacer();

… // « effacement » des spécificités du magicien }

„ L’appel de la méthode d’effacement du personnage est faite par l’instruction :

„ CPersonnage :: effacer();

Polymorphisme

„ La méthode « deplacer » de la classe CPersonnage effectue le traitement suivant :

„ Effacement du personnage à sa position courante

„ Modification de la position courante du personnage

„ Dessin du personnage à sa nouvelle position void CPersonnage :: deplacer ( int nx, int ny ) { effacer();

posx=nx; posy=ny;

dessiner();

}

(5)

25

Polymorphisme

„ Déplacer un magicien consiste à :

„ Effacer le magicien à sa position courante

„ Changer la position

„ Dessiner le magicien à la nouvelle position

„ Cette méthode est donc

„ « similaire » à la méthode définie pour un personnage

„ excepté qu’il faut utiliser les méthodes « dessiner » et

« effacer » de la classe dérivée CMagicien au lieu de celles de la classe CPersonnage.

„ La classe CMagicien hérite de la méthode « deplacer ».

26

Polymorphisme

„ On souhaite récupérer la méthode « deplacer » définie dans la classe CPersonnage

„ Cette méthode « deplacer » fait appel aux méthodes

« dessiner » et « effacer »

„ dont il existe deux versions homonymes sur les classes CPersonnage et CMagicien

„ Nécessité de s'assurer que ce sont bien les méthodes

« dessiner » et « effacer » de la classe CMagicien qui seront utilisées pour un magicien.

27

Polymorphisme

„ Le compilateur n'est pas en mesure de faire le choix car lors de la compilation,

„ on ne sait pas encore de façon précise lequel des descendants va demander l'exécution de la méthode « déplacer ».

„ Nécessité de différer le choix de l'homonyme à appeler

„ et prévoir tous les cas possibles.

„ On appelle ligature dynamique cette méthode de résolution d'appels.

28

Polymorphisme

„

Le choix qui a été fait en C++ est de demander à l'utilisateur :

„

de signaler par le mot clé virtual toute méthode

„

pour laquelle la ligature doit être dynamique.

„

On parle de méthodes virtuelles.

Polymorphisme

class CPersonnage /* deuxième version */

{ protected : char nom[30];

int posx, poy;

public

CPersonnage();

virtual void dessiner(); // méthode virtuelle virtual void effacer(); // méthode virtuelle void deplacer(int, int);

};

Polymorphisme

„ On pourra alors de façon transparente, utiliser « deplacer » sur un

« CPersonnage » ou sur un « CMagicien ».

CPersonnage perso;

perso.deplacer();

/* utilise les méthodes « dessiner » et « effacer » de personnage dans la méthode « deplacer » */

CMagicien mage;

mage.deplacer();

/* utilise les méthodes « dessiner » et « effacer » du magicien dans la méthode « deplacer » sans redéfinir cette méthode dans la classe CMagicien*/

„ Lors des appels, le compilateur va détecter le type d’objet réalisant l’appel et aller sélectionner la méthode adéquate.

(6)

31

Programmation avancée en C++

„

Rappel : passages de paramètres

„

La généricité (patrons)

„

Les exceptions

„

Les flots

32

Langage C++

Rappel : passages de paramètres

„

Il n’existe en langage C qu’un mode de passage des paramètres qui est

„

le mode lecture aussi appelé par valeur.

„

Pour faire une passage en écriture ou lecture/écriture i.e. par adresse, il faut le faire explicitement :

„

À la charge du programmeur

33

Langage C++

Rappel : passages de paramètres

„

Exemple 1 : Passage par valeur

„ On considère la fonction suivante : int addition(int x, int y)

{return x+y;} // les valeurs de x et y sont seulement « lues »

„Avec les définitions suivantes :

„int u=1, v=2, res;

„int *pu, *pv;

„pu = new int; *pu = 4; pv=&v;

„Les deux appels ci-dessous sont corrects

„res = addition(u,v);

„res= addition (*pu, *pv);

34

Langage C++

Rappel : passages de paramètres

„

Exemple 2 : Passage par adresse « explicite »

„ On considère la fonction suivante : void echange(int *px, int *py)

{int z; z= *px; *px= (*py); *py = z; }

// les valeurs pointées par px et py peuvent être « modifiées »

„Avec les définitions suivantes :

„int u=1, v=2, res;

„int *pu, *pv;

„pu = new int; *pu= 4; pv=&v;

„Les deux appels ci-dessous sont corrects

„echange(&u,&v);

„echange (pu, pv);

Langage C++

Rappel : passages de paramètres

„

Le langage C++ a introduit un mode de passage par référence

void echange(int & x, int & y)

{ int z; z=x; x=y; y=z;}

„

L’appel peut se faire sous la forme :

„int u=4, v=5;

„echange(u,v);

Langage C++

Rappel : passages de paramètres

„

Le langage C++ a conservé le mode de passage par valeur du langage C.

„

int addition(int x, int y)

„{ return x+y;}

„

L’appel peut se faire sous la forme

„int u=4, v=5, w ;

„w= addition(u,v);

(7)

37

Langage C++

Rappel : passages de paramètres

„ Lors un paramètre doit être passé en lecture (par valeur) et que son type n’est pas un type de base (int, float, …).

„ On peut utiliser une autre forme proposée par C++,

„ Qui consiste à faire une passage par référence mais en précisant que le paramètre effectif ne sera pas modifié

„ Économie d’espace et gain de vitesse

„ void echangePerso(const CPersonnage &p1, const CPersonnage &p2);

„ L’appel peut être fait sous la forme : CPersonnage perso1, perso2;

echange (perso1, perso2);

38

Généricité

„

Définir un modèle

„ de fonctionnement d'une fonction,

„ de définition d'une classe

qui puisse s'appliquer à différents types de données.

„

Par exemple, pour une pile d'objets

„ Les opérations de manipulation de la pile sont

"indépendantes" du type des objets manipulés

„empiler, dépiler, est_vide, sommet

39

Généricité

„

Le type des objets peut être

„simple : entier, caractère, …

„ou complexe : classe

sans influence sur le mode de fonctionnement de la pile

„

Généricité : avoir des outils qui permettent de manipuler des objets "formels"

„choix du type "effectif" lors de la déclaration de la pile

„instanciation du type générique

40

Généricité

„

Autre généricité souhaitée :

„possibilité de définir le fonctionnement d'une fonction

„sans utiliser le mécanisme de surcharge pour chaque type possible

„

Mais en la décrivant de façon "formelle"

„

Instanciation au moment de l'appel en fonction du type des paramètres effectifs utilisés

Généricité des fonctions

„ Exemple :

„ On souhaite définir une fonction qui retourne la valeur maximum de deux valeurs passées en paramètres.

„ utilisable sur tous les types de base int, char, float, double, etc...

„ 1ère solution :

„ Surcharger la fonction pour tous les types possibles

„ int max (int x, int y);

„ float max (float x, float y);

„ Solution lourde et peu satisfaisante

Généricité des fonctions

„ 2ème solution :

„ Définir "max" sur un type formel

„ Spécification d'un nom de type formel T

„ Utilisation de ce type formel pour décrire la fonction template <class T>

T max (T x, T y) { if (x > y)

return (x);

else return(y);

}

(8)

43

Généricité des fonctions

„ Utilisation de cette fonction paramétrée void main (void)

{ int u=5, v=6, w;

float s=5.7, f=7.8, g;

/* appel de max avec les entiers */

w= max (u,v);

cout << "max entier = " << w;

/* appel de max avec les réels */

g= max(s,f);

cout << "max réel = " << g;

}

44

Généricité des fonctions

„

Remarques

„

Le type T peut être un nom de type (ici int, float) ou de classe

„

T peut être un type prédéfini pour lequel l'opérateur de comparaison ">" est prédéfini

„

ou bien T peut être un type utilisateur pour lequel l'opérateur ">" a été surchargé

„

pas de limite grâce au mécanisme de surcharge des opérateurs

45

Généricité : les modèles de classe

„ Modèles de classe = classes génériques = patrons

„ Utilisation de la notion de type formel pour définir une classe générique.

„ Supposons par exemple définir une classe CEnsemble qui peut contenir n’importe quels types d’objets avec des fonctionnalités classiques

„ Ajout d’un élément

„ Suppression d’un élément

„ Test si un élément est dans l’ensemble

„ Union de 2 ensembles

„ Etc.

46

Généricité : les modèles de classe

„ Définition de la classe générique

„ T est le nom du type formel utilisé pour la définition de la classe template <class T>

class CEnsemble { private :

T tab[MAX];

// L’ensemble est géré par un tableau de MAX éléments de type T int nbe;

public : CEnsemble();

void ajout(T);

void supprime(T);

bool appartient(T);

};

Généricité : les modèles de classe

„ Définitions des différentes méthodes

„ rappel de la forme générale :

„ type_retour nom_classe :: nom_fonction (paramètres)

„ Ici, la classe est une classe générique il faut donc

„ Préciser le nom du paramètre formel utilisé pour la description de la méthode

„template <class T>

„ Donner le nom de la classe générique

„CEnsemble<T>

Généricité : les modèles de classe

„ Définition du constructeur : template <class T>

CEnsemble<T> :: CEnsemble() { nbe=0;}

„ Définition de la méthode « ajout » template <class T>

void CEnsemble<T> :: ajout (T elem) { if (nbe < MAX && ! appartient(elem))

tab[nbe++]=elem;

}

(9)

49

Généricité : les modèles de classe

„ Définition de la méthode « appartient » template <class T>

bool CEnsemble<T> :: appartient (T elem) { bool trouve = false;

int i=0;

while (i < nbe && !trouve)

if (tab[i] == elem) trouve=true;

else i++;

return trouve;

}

„ Cette méthode utilise l’opérateur == pour comparer 2 objets du type formel T

„ Il faudra que cet opérateur soit défini pour le type effectif utilisé pour instancier la classe CEnsemble, i.e.

„ Type de base (int, float, …)

„ Classe définie par l’utilisateur mais avec une surcharge de l’opérateur ==

50

Généricité : les modèles de classe

„

Utilisation de cette classe générique.

„

Instanciation du type formel par un type effectif à la déclaration d'un objet de cette classe

„

CEnsemble<int> ensEntier;

„ Instanciation du type T par le type int,

„ Déclaration de la variable ensEntier comme étant un ensemble d’entiers

„Le type int possède l’opérateur de comparaison ==

51

Généricité : les modèles de classe

„

Censemble<CPersonnage> ensPerso;

„ Instanciation du type T par le type CPersonnage,

„ Déclaration de la variable ensPerso.

„

Cette instanciation est correcte seulement si l’opérateur == a été défini dans la classe CPersonnage.

„ bool operator==(CPersonnage p);

52

Généricité : les modèles de classe

„ Le nombre de paramètres formels n'est pas limité à 1,

„ on peut en avoir plusieurs.

template <class X, class Y>

class Compose { private :

X attribut1;

Y attribut2;

public : ...

};

Généricité : les modèles de classe

„

Une classe peut être paramétrée

„

par "autre chose" qu'un type formel

„

par exemple une valeur qui représente une taille, ...

Généricité

Définition d'un buffer d'objets

„ Généricité sur le type des objets

„ Généricité sur la taille du buffer template <class T, int taille = 64>

/* 64 est la valeur par défaut de l'élément taille */

class Buffer { T *buf;

public : /* constructeur */

Buffer();

...

};

(10)

55

Généricité

Définition d'un buffer d'objets

„ Définition du constructeur qui alloue dynamiquement le buffer.

template <class T, int taille=64>

Buffer<T,taille> :: Buffer() { buf= new T [taille];

}

„ Le nom de la classe générique est Buffer<T,taille>

„ L’instruction buf= new T [taille] alloue un tableau de taille « taille » d’éléments de type T.

56

Généricité

Définition d'un buffer d'objets

„

Déclaration d'un objet de la classe

„

b est une variable de type Buffer avec une instanciation du type formel avec des entiers et une taille fixée à la valeur 100.

„

Buffer <int,100> b;

„

Tableau de 100 entiers,

„

réservation dynamique des éléments par appel du constructeur de la classe générique

57

Généricité - Conclusion

„

La généricité est un mécanisme qui permet :

„

De définir des méthodes ou des classes formelles manipulant des types d'objets

« généraux ».

„

Et de spécifier ces types lors de l'utilisation de

la classe ou de la méthode.

Références

Documents relatifs

Meyerson précise qu’il ne vise pas le pan-algébrisme de l’école de Marburg, pourtant présenté comme la « forme la plus définie » d’idéalisme

The existence of spiral breakdown states is shown to proceed from a global instability of the axisymmetric breakdown solution to helical disturbances with azimuthal

The micro reading task consisted in extracting GO terms from a single MEDLINE abstract, as in the Trieschnigg et al’s work; the macro reading task consisted in extracting GO terms

En vertu de ses capacités à manipuler les données relationnelles, à créer des règles d’association permettant d’évaluer conjointement les caractéristiques des objets et

La vitesse moyenne d’un mobile sur une distance et pendant une durée est une vitesse fictive vitesse fictive vitesse fictive vitesse fictive correspondant à la

Kramp , un nouvel instrument , suscep- tible sans doute de perfectionrierrient ; mais qui , tel qu’il est , peut déjà, dans un grand nombre de circonstances,

Par exemple, pour d´eclarer une variable strNomDeFamille de type chaˆıne de caract`eres et lui attribuer la valeur ”Tavenard”, en VB, on a :. Dim strNomDeFamille as