Etiquettes de protection.
Les étiquettes de protection.
Dans le chapitre précédent vous aurez sûrement remarqué la présence d'un "public:", nous allons voir ici à quoi sert ce mot-clé et les notions qu'accompagne ce mot-clé.
En C++ il y a trois niveau de protection au sein des class:
- public: il n'y a aucune restriction, toutes les fonctions peuvent avoir accès à toutes les variables membres de la classe qui sont sous cette étiquette, et toutes les fonctions sous l'étiquette public peuvent être appellées.
- private: c'est la restriction totale, à savoir qu'une variable sous l'étiquette private n'est accessible que par les fonctions membres de la classe.
- protected: ce niveau de protection sera expliqué dans le chapitre sur les héritages.
Vous allez très vite dire: "Mais à quoi ca sert?". Cela sert principalement a ne pas faire d'erreurs et à ce que toutes les fonctions ne puissent modifier toute les variables. Mais cela sert aussi a utiliser la notion d'encapsulation qui est généralement indispensable pour ne pas faire d'erreurs.
Encapsulation
L'encapsulation est le concept qui va nous permettre d'écrire un programme propre... Vous allez me dire, est-ce que c'est vraiment utile? Eh bien, dans l'absolu, non... Du fait que: l'encapsulation n'est pas quelque chose d'obligatoire, mais il est à savoir que cette notion rend le programme plus facilement déboguable...
L'encapsulation, va "jouer" sur les niveaux d'accès de façon à rendre le programme plus lisible. Ainsi, on n'utilisera pas directement le nom de la variable pour changer sa valeur et l'utiliser mais une fonction.
Ce processus utilise deux type de fonctions.
- Les accesseurs: qui renvoient la valeur d'une variable de la classe.
- Les mutateurs: qui permettent de modifier la valeur d'une variable.
Faisons un programme qui ouvre et ferme une porte avec et sans l'encapsulation:
#include <iostream.h>
class Porte {
public:
bool etat; //variable dans la quel on stocke l'etat ouvert ou ferme de la porte
};
int main (void) {
Porte uneporte;
uneporte.etat=true; // ouverture de la porte
cout<<"La porte s'ouvre"<<endl;
uneporte.etat=false; // fermeture de la porte
cout <<"La porte se ferme"<<endl;
return0;
}
Maintenant avec l'encapsulation:
#include <iostream.h>
class Porte {
private:
bool etat; //variable dans la quel on stocke l'etat ouvert ou ferme de la porte
public:
void SetEtat (bool ouvert);
bool GetEtat (void);
};
void Porte::SetEtat (bool ouvert)
{
etat=ouvert;
if (etat)
cout<<"la porte s'ouvre";
else
cout <<"La porte se ferme";
} //On pourrait meme ici verifier que l'on ouvre pas une porte deja ouverte...
bool Porte::GetEtat (void) {
return etat;
}
int main (void) {
Porte uneporte;
uneporte.SetEtat(true);
uneporte.SetEtat(false);
if (uneporte.GetEtat())
cout <<"La porte est fermee";
return0;
}
Commentaire.
Bien que le second programme soit plus long et plus compliqué, vous remarquerez que ce sont les fonctions membres qui sont développées. Ainsi, on voit bien que le main est plus simple, et bien plus facilement comprehensible. C'est pourquoi je recommande l'utilisation des accesseurs/mutateurs lors de l'emploi de classes. Bien évidement, étant donné le peu de complexite du programme, on aurait pu se passer de cette encapsulation... Mais vu la qualité du code, son utilisation peut provoquer un vrai manque de lisibilité dans votre programme...
Autres utilité de l'encapsulation.
On se sert aussi très souvent des accesseurs pour faire ce que l'on apelle un controle de validité. Cela consiste à verifier que la valeur que l'on demande de donner à la variable est logique. Par exemple, verifier qu'une note ne vale pas 22/20, qu'une pièce d'echec soit bien sur l'echiquier...
Ou encore à faire un traitement automatique à chaque changement de la valeur d'une variable. Par exemple, si dans un jeu d'échecs la position d'une pièce change, il peut être bon de réactualiser l'écran... On peut encore trouver des tas d'utilités à l'encapsulation, mais je pense que les principales utilités ont été données. Si vous avez d'autes idées que je n'ai pas eues, n'hésitez pas à m'écrire.