Découvrez la notion de portée d'une variable
Chaque variable n'est disponible (et accessible) que dans le contexte dans lequel elle a été déclarée. Pour déterminer ce contexte, reportez-vous aux marques d'ouverture et de fermeture les plus proches qui entourent la déclaration. La plupart des langages de programmation utilisent des accolades ouvrantes et fermantes ( { }
) pour marquer le début et la fin d'un bloc de code. Jetez un œil à cet exemple :
Il n'est pas nécessaire de comprendre l'intégralité de ce code. Il vous suffit de vous concentrer sur les accolades ouvrante et fermante. 🙂 Quand nous parlons de la disponibilité d'une variable dans un contexte, nous faisons référence à la portée. Ici, vous pouvez voir que la variable racine
a été déclarée entre les deux accolades (ouvrante et fermante) entourées en violet. La portée de cette variable correspond à tout ce qui se trouve entre ces deux accolades.
La portée d'une variable peut être locale ou globale, en fonction de l'endroit où la variable est déclarée. Une variable globale peut être disponible pour toutes les classes et méthodes d'un programme, alors qu'une variable locale ne peut être disponible que dans la méthode dans laquelle elle est déclarée :
Ici, nous avons un peu élargi le code et étendu notre premier bloc de code pour en inclure un autre ! Si vous observez bien le cadre délimité par les lignes violettes, vous pouvez voir que les accolades du premier bloc englobent tout le code du deuxième bloc. Ensuite, vous pouvez constater qu'une nouvelle variable espion
a été déclarée dans une portée locale (cadre vert).
La variable racine
ayant été déclarée dans le cadre de la portée globale, elle est accessible à tous les éléments se trouvant entre parenthèses violettes, y compris ceux déclarés dans la portée locale. Dans le deuxième bloc de code, la ligne juste en dessous de la déclaration de la variable « espion » utilise la variable racine
. Cette ligne de code est valide !
En revanche, tous les éléments faisant partie de la portée locale sont inaccessibles à ceux de la portée globale et à ceux des autres blocs de code locaux. Prenons un autre exemple :
Dans cet exemple, nous avons ajouté un autre bloc de code, qui a sa propre portée locale et sa propre variable, autreEspion
. Maintenant, regardez la dernière ligne du bloc de notre variable espion :
Console.WriteLine(autreEspion); // Erreur
On dirait qu'il y a une erreur ! L'instruction essaie en effet d'utiliser la variable autreEspion
. Cela n'est pas possible, car la variable autreEspion
ne se trouve ni dans la portée globale ni dans la même portée locale. Cela signifie que ce bloc de code ne peut pas y accéder. La variable autreEspion
est disponible uniquement dans le bloc de code dans lequel elle a été déclarée.
L'inverse est également vrai. Vous voyez que la dernière ligne de notre dernier bloc de code présente, elle aussi, une erreur :
Console.WriteLine(espion); // Erreur
Ici, le code essaie d'utiliser la variable espion
, déclarée dans un autre bloc de code. Mais cela n'est pas possible, car la variable espion
ne se trouve pas dans la même portée que le bloc de code qui essaie de l'utiliser.
Découvrez la portée des variables dans les classes
Lorsque vous déclarez une classe, les mêmes règles générales concernant la portée s'appliquent : chaque variable n'est accessible qu'au sein du bloc dans lequel elle a été déclarée. Voyons cela avec une classe Licorne :
Tout comme dans notre premier exemple, on peut voir ici des variables de classe globales et locales. Entrons dans le détail :
Les variables
hauteur
etpuissance
sont des champs de la classe et sont accessibles partout dans la classe.La variable
minutesDeSommeil
n'est accessible que dans la portée locale du bloc de code dans lequel elle est déclarée.La variable
minutesDeCourse
n'est accessible que dans la portée locale du bloc de code dans lequel elle est déclarée.
La portée d'une variable limite (par définition) son accessibilité. Cependant, les champs de classe sont accessibles en dehors de la classe et peuvent être utilisés par tout autre bloc de code.
Dans notre exemple, il s'agit des champs hauteur
et puissance
. Si vous déclarez une variable de type licorne, vous pourrez lire ou modifier ces valeurs :
Licorne licorne = new Licorne();
Console.WriteLine("Je connais sa taille : " + licorne.hauteur);
// et je peux changer sa puissance !
licorne.puissance = “Double.zero”; // pas drôle !
La possibilité de manipuler des variables de classe peut avoir des conséquences importantes. Heureusement, vous avez la main sur ce comportement ! Avant de découvrir comment procéder, entraînez-vous à manipuler la portée des variables.
Testez par vous-même !
Prêt à coder ? Pour accéder à l’exercice, suivez ce lien.
Maîtrisez les contrôles d'accès
Nous allons mettre en place un contrôle d'accès en implémentant un accès restreint à une classe ou à un assembly. Vous savez déjà ce qu'est une classe.
Un assembly est une bibliothèque de code compilé utilisée pour le déploiement, le versionnage et la sécurité. Il s'agit d'une collection de classes et de ressources conçues pour fonctionner ensemble et former une unité logique de fonctionnalité. De nombreux assemblys sont fournis avec le .NET Framework. Leur implémentation est loin de se limiter à ce que les développeurs qui y ont recours peuvent voir et utiliser. Ceci s'explique par le fait que l'accès aux détails de l'implémentation est limité. C'est ce qu'on appelle le contrôle d'accès.
Niveaux d'accès
En C#, vous devez utiliser un des mots-clés suivants pour désigner un niveau d'accès :
Public : implémentation visible pour tous (niveau le moins restrictif).
Protected : implémentation visible pour le package et l'ensemble de ses sous-classes.
Internal : implémentation généralement visible uniquement par le package dans lequel elle se trouve.
Private : implémentation accessible uniquement dans le contexte dans lequel elle est définie (à l'intérieur de la classe dans laquelle elle se trouve).
La mise en place de ces restrictions distinctes facilite grandement le développement. Vous n'avez pas à vous soucier de la visibilité non désirée de votre implémentation ni, plus important encore, des modifications non désirées.
Placez le mot-clé approprié devant chaque déclaration concernée :
class Licorne
{
// Propriétés
private int taille = 170;
public string puissance = "Double.infinity";
// Méthodes
private void Dormir()
{}
public void Courir()
{}
}
Ensuite, si vous essayez d'accéder aux membres privés depuis l'extérieur de la classe, vous obtenez des erreurs :
Licorne licorne = new Licorne();
Console.WriteLine(licorne.puissance); // OK
licorne.taille = 180; // Erreur
licorne.Dormir(); // Erreur
licorne.Courir(); // OK
Des niveaux d'accès peuvent être attribués aux éléments de classe ainsi qu'aux classes :
public class ClassePublic {
}
private class ClassePrivee {
}
Spécifier des niveaux d'accès pour les membres des classes améliore la sécurité et offre une meilleure lisibilité du code. Lorsqu'un développeur prépare un fichier source, il précise toujours clairement quels éléments peuvent être utilisés en externe.
En résumé
Ce chapitre vous a permis d'en savoir plus sur l'accessibilité des variables :
La portée d'une variable est la zone de code où elle a été déclarée.
La portée globale s'applique à tous les blocs de code, y compris les classes.
Une autre méthode efficace pour contrôler l'accès aux variables et aux fonctions consiste à utiliser des niveaux d'accès : public, protected, internal et private.