Académique Documents
Professionnel Documents
Culture Documents
Dans les programmes que vous avez double surface(double largeur, double hauteur);
écrits jusqu’à maintenant, les notions int main()
I de variables/types de données {
double largeur(3.0);
I et de traitement de ces données double hauteur(4.0);
étaient séparées :
cout << "La surface du rectangle est : "
<< surface(largeur, hauteur) << endl;
opèrent sur
return 0;
}
traitements données
double surface(double largeur, double hauteur)
{
return largeur * hauteur;
influencent
}
programmeur programmeur 1. L’intérêt de regrouper les traitements et les données conceptuellement reliées
utilisateur concepteur/développeur est de permettre une meilleure visibilité et une meilleure cohérence au
programme, d’offrir une plus grande modularité.
accord double largeur(3.0); Rectangle rect(3.0, 4.0);
double hauteur(4.0); cout << "Surface : "
<< rect.surface()
cout << "Surface : " << endl;
<< surface(largeur, hauteur))
utilisation du type prototype définition d'un nouveau type (classe) << endl;
Pourquoi abstraire/encapsuler ? (2) Encapsulation / Abstraction : Résumé
OBJET
2. L’intérêt de séparer les niveaux interne et externe est ON
RACTI attributs méthodes
de donner un cadre plus rigoureux à l’utilisation des T
ABS
objets utilisés dans un programme
Interface
Les objets ne peuvent être utilisés qu’au travers de
(partie visible) (vide)
leurs interfaces (niveau externe)
et donc les éventuelles modifications de la
structure interne restent invisibles à l’extérieur
(même idée que la séparation prototype/définition Détails d'
d’une fonction) Implémentation
(partie interne/cachée)
Règle : les attributs d’un objet ne doivent pas être accessibles depuis l’extérieur,
mais uniquement par des méthodes.
En programmation Objet : surface En C++ une classe se déclare par le mot-clé class.
I le résultat des processus d’encapsulation largeur
Exemple : class Rectangle { ... };
et d’abstraction s’appelle une classe hauteur
31.2
34.3
int main()
{ Exemple :
Rectangle rect1; les attributs hauteur et largeur, de type double,
de la classe Rectangle pourront être déclarés par :
return 0;
} class Rectangle {
double hauteur;
double largeur;
};
Accès aux attributs Notre programme (2/4)
#include <iostream>
using namespace std;
class Rectangle {
L’accès aux valeurs des attributs d’une instance de nom nom_instance double hauteur;
se fait comme pour accéder aux champs d’une structure : double largeur;
};
nom_instance.nom_attribut
int main()
Exemple : {
la valeur de l’attribut hauteur d’une instance rect1 Rectangle rect1;
de la classe Rectangle sera référencée par l’expression :
rect1.hauteur = 3.0;
rect1.hauteur rect1.largeur = 4.0;
return 0;
}
type_retour nom_methode (type_param1 nom_param1, ...) const type_retour nom_methode (type_param1 nom_param1, ...) const
Exemple : class Rectangle { Si vous déclarez une action en tant que prédicat (const), vous aurez à la
// ... compilation le message d’erreur :
double surface() const;
}; assignment of data-member ‘...’ in read-only structure
3.0
rect2
4.0
rect1.largeur 11.5
rect3
rect1.hauteur 3.8
rect2.hauteur 31.2
rect3.largeur 34.3
Note : Si aucun droit d’accès n’est précisé, c’est private par défaut.
private:
// déclaration des attributs
double hauteur;
double largeur;
};
Jeu de Morpion : bien encapsuler (2) Jeu de Morpion : bien encapsuler (3)
private:
/**
* Place un coup sur le plateau en position (ligne, colonne).
* Ligne et colonne : 0, 1 ou 2. public:
*/ bool placer_rond( size_t ligne, size_t colonne) {
bool placer_coup(size_t ligne, size_t colonne, CouleurCase coup) { return placer_coup(ligne, colonne, ROND);
if ( ligne >= grille.size() }
or colonne >= grille[ligne].size() ) { bool placer_croix(size_t ligne, size_t colonne) {
// traitement de l'erreur ici return placer_coup(ligne, colonne, CROIX);
} }
if (grille[ligne][colonne] == VIDE) {
// case vide, on peut placer le coup // ici on peut rajouter une methode get_joueur_gagnant() const
grille[ligne][colonne] = coup;
return true; }; // fin de la classe JeuMorpion
} else {
// case dejà prise, on signale une erreur.
// ...
return false;
} // suite
Jeu de Morpion : bien encapsuler (4) Jeu de Morpion encapsulé : avantages
Comment faire maintenant pour faire un rond sur la case du milieu ? I Validation : il est impossible de mettre une valeur invalide dans le tableau
JeuMorpion jeu; (autre que 0, 1, ou 2)
jeu.initialise();
valide = jeu.placer_rond(1, 1); // bool valide déclaré plus haut
I Validation : il est impossible de cocher une case déjà cochée.
I Séparation des soucis : le programmeur-utilisateur n’a pas besoin de savoir
comment le plateau est stocké, ni qu’il utilise des entiers, ni quelles valeurs
Et pour faire une croix sur la 1re ligne, 2e colonne ?
correspondent à quoi.
valide = jeu.placer_croix(0, 1); I Le code est compréhensible même par un profane – le nom des méthodes
exprime clairement ce qu’elles font et s’explique de lui-même.
On aurait pu également décider d’appeler les colonnes 1, 2, 3 au lieu de 0, 1, 2 :
I Si on essaie de faire une opération invalide (cocher deux fois la même case, ou
c’est une question de convention. C’est justement ce sur quoi il faut se mettre
une case en dehors du tableau), on obtient un message compréhensible.
d’accord quand on définit une interface.