Accueil > Programmer avec Java > Décomposition et modularité >
đ PortĂ©e des variables
Survol et attentes
Définitions
- PortĂ©e dâune variable
- lâĂ©tendue du code source oĂč le nom de variable est reconnue, se limitant aux accolades
{}du bloc qui le contiennent. Intentionnellement, la portĂ©e des variables est limitĂ©e pour mieux contrĂŽler lâaccĂšs aux informations et pour permettre la rĂ©utilisation des mĂȘmes noms de variables dans diffĂ©rentes parties du code source sans crĂ©er des conflits de noms. - Variable globale
- une variable déclarée en dehors de toutes les méthodes. Toutes les méthodes dans le fichier peuvent accéder directement à ces variables.
- Variable locale
- une variable dĂ©clarĂ©e dans une mĂ©thode ou, Ă lâintĂ©rieur des mĂ©thodes, dans une structure de contrĂŽle (incluant leurs dĂ©clarations). Câest pourquoi les mĂ©thodes doivent recevoir des arguments et retourner des valeurs pour passer de lâinformation aux autres mĂ©thodes.
- Constante globale
- une variable globale qui est déclarée
finalpour indiquer quâelle ne peut pas ĂȘtre modifiĂ©e. Les constantes globales sont utilisĂ©es pour des valeurs qui ne changent pas dans le programme et qui sont utilisĂ©es dans plusieurs mĂ©thodes. Par exemples : une rĂ©fĂ©rence au Scanner de la console, des valeurs de rĂ©fĂ©rence, des codes de couleur ANSI, des constantes mathĂ©matiques. Nommant ce type de valeur dans une constante globale rend le code plus lisible que dâinclure la valeur littĂ©rale partout oĂč elle est utilisĂ©e.
Objectifs dâapprentissage
Ă la fin de cette leçon vous devrez ĂȘtre en mesure de :
- Décrire la différence entre une portée globale et une portée locale.
- Savoir quelle variable, entre deux variables de mĂȘme nom, sera prĂ©fĂ©rĂ©e en considĂ©rant sa portĂ©e.
- Identifier si une variable spécifique est accessible ou non dans un endroit donné du code source.
- DĂ©crire des raisons de prĂ©fĂ©rer lâutilisation de variables locales Ă lâutilisation de variables globales.
CritĂšres de succĂšs
- Je minimise la visibilité des variables en leur donnant la plus petite portée nécessaire, ce qui veut dire utiliser une majorité de variables locales.
- Jâutilise les variables globales dans mon code lorsque cela rend le code plus lisible et plus facile Ă maintenir.
- Jâutilise des constantes globales pour les valeurs qui ne changent pas dans mon programme et qui sont utilisĂ©es dans plusieurs mĂ©thodes.
Portée des variables
La portĂ©e dâune variable est synonyme de sa visibilitĂ© : jusquâĂ quels endroits dans le code est-ce quâon peut âvoirâ cette variable (la nommer sans erreur de syntaxe)?
Les variables globales sont visibles partout dans un programme1. Elles sont dĂ©clarĂ©es Ă lâextĂ©rieur des mĂ©thodes et on peut les lire et les modifier dans toutes les mĂ©thodes du programme.
Câest un avantage parce quâon a pas besoin dâĂ©changer cette information entre les mĂ©thodes via des paramĂštres ou des valeurs de retour.
Câest un dĂ©savantage parce nâimporte quelle partie de notre code peut modifier cette information, ce qui peut rendre le code difficile Ă corriger, briser la modularitĂ© du code (les sous-problĂšmes sont maintenant fusionnĂ©s autour de lâinformation partagĂ©e) ou introduire des problĂšmes de sĂ©curitĂ© (modifications possibles au-delĂ des intentions originales).
Les variables locales sont seulement visibles dans la mĂ©thode oĂč elles sont dĂ©finies. Les paramĂštres et les variables dĂ©finies dans le corps dâune mĂ©thode sont des variables locales. JusquâĂ prĂ©sent, nous avons seulement utilisĂ© des variables locales dans nos programmes.
Les avantages des variables locales sont que : lâinformation existe seulement Ă lâendroit oĂč elle sera directement utile et plusieurs variables dans un programme peuvent avoir le mĂȘme nom sans interfĂ©rence parce que leurs portĂ©es ne se croisent pas.
Le dĂ©savantage est que pour partager lâinformation locale Ă une autre mĂ©thode, il faut âpasser des messagesâ avec des arguments/paramĂštres et des valeurs de retour. Cela peut parfois rendre la liste des paramĂštres assez longue que câest difficile Ă se rappeler quel paramĂštre va Ă quelle position.
---------------fichier------------------
déclaration de variable globale
méthode() {
déclaration de variable locale
}
méthode( les paramÚtres sont des variable locales ) {
}
----------------------------------------
Variables globales
Câest rarement une bonne idĂ©e dâutiliser des variables globales parce que le code devient beaucoup plus dur Ă dĂ©boguer. Mais il y a quelques cas oĂč câest une solution bien adaptĂ©e :
La valeur est constante et requise par plusieurs méthodes
On peut alors déclarer une constante globale en le préfixant avec le mot-clé final et en appliquant la convention du nom en majuscules. Les Scanner pour la console, les codes de couleur ANSI et les structures de données (à venir dans une prochaine section du cours) sont des exemples de bons candidats de constantes globales.
Dans ce cas, le fait que la valeur soit constante élimine la possibilité de modification inappropriée et la portée globale peut réduire la complexité et la répétitivité des déclarations et appels de méthodes.
La variable représente un état du programme que plusieurs méthodes doivent consulter ou peuvent modifier
Plusieurs informations dans un jeu tombent dans cette catĂ©gorie. Si ces variables nâĂ©taient pas globales, la liste des paramĂštres pour la plupart des mĂ©thodes deviendrait ingĂ©rable. De plus, la restriction avec Java dâune seule valeur de retour rend lâexportation de plus quâune modification Ă ces valeurs, si pas impossible, du moins trĂšs complexe. Cette complexitĂ© additionnelle rendrait le code plus dur Ă lire, Ă dĂ©boguer et Ă modifier. Les risques liĂ©s aux variables globales sont alors moindre que les risques avec lâautre approche.
Exemples de constantes globales
Fichier GlobalScanner.java
import java.util.*;
final Scanner CONSOLE = new Scanner(System.in); // visible globalement
void main() {
// final Scanner CONSOLE = new Scanner(System.in); // ne serait pas visible dans getName ni getInteger
String name = getName();
int age = getInteger("age");
System.out.printf("%s a %d ans.\n", name, age);
}
String getName() {
System.out.print("Quel est votre nom? > ");
return CONSOLE.nextLine();
}
int getInteger(String what) {
System.out.printf("Entrez un nombre entier pour votre %s > ", what);
int result = CONSOLE.nextInt(); // pour consommer la valeur
CONSOLE.nextLine(); // pour consommer le retour de ligne aussi
return result;
}
Ici le Scanner pour la console est utilisĂ©e dans plusieurs mĂ©thodes et ne change pas de valeur (rĂ©fĂšre toujours Ă System.in), alors câest un bon candidat de constant globale.
Notez que la dĂ©claration commence avec final disant Ă Java que cette valeur ne peut jamais changer durant lâexĂ©cution. Notez aussi quâon a Ă©crit le nom en majuscules afin de mieux le repĂ©rer comme constante.
Fichier GlobalColorCodes.java
import java.util.*;
final String RED = "\033[0;31m";
final String GREEN = "\033[0;32m";
final String YELLOW = "\033[0;33m";
final String RESET = "\033[0m";
void printRed(String text) {
System.out.println(RED + text + RESET);
}
void printGreen(String text) {
System.out.println(GREEN + text + RESET);
}
void printYellow(String text) {
System.out.println(YELLOW + text + RESET);
}
void main() {
printRed("Ceci est un message d'erreur!");
printGreen("Ceci est un message de succĂšs!");
printYellow("Ceci est un avertissement");
System.out.printf("%sCe texte%s est en %ssurbrillance%s%s!!!%s",
GREEN, RESET, YELLOW, RESET, RED, RESET);
}
Ici on a plusieurs constantes globales pour les différents codes de couleur pour le texte à la console. Ces constantes sont utilisées dans les différentes méthodes, incluant main qui fait un usage sur mesure pour la derniÚre phrase.
Variables globales dâĂ©tat
Voici un exemple banal pour quelques variables globales pour un jeu.
Fichier : GlobalGameState.java
int lives = 3;
int xp = 0;
boolean hasWeapon = true;
boolean hasHorse = true;
void diedInBattle() {
xp += 5;
lives--;
hasWeapon = false;
System.out.println("Vous ĂȘtes mort au combat et avez perdu votre arme!");
}
void diedWhileRiding() {
xp += 2;
lives--;
hasHorse = false;
System.out.println("Vous ĂȘtes mort en tombant de votre cheval!");
}
void showStats() {
System.out.println("Vies : " + lives);
System.out.println("Points d'expérience : " + xp);
System.out.println("Vous avez une arme : " + hasWeapon);
System.out.println("Vous avez un cheval : " + hasHorse);
}
void main() {
showStats();
diedInBattle();
showStats();
diedWhileRiding();
showStats();
}
Priorité de nom selon la portée
Une des caractĂ©ristiques dâun programme avec diffĂ©rentes portĂ©es de variables est que le mĂȘme nom peut ĂȘtre dĂ©clarĂ© Ă plusieurs endroits sans conflits en autant que leurs portĂ©es soient diffĂ©rentes.
Sâil y a deux variables du mĂȘme type et du mĂȘme nom, mais une est globale est lâautre est locale, la version locale sera toujours utilisĂ©e en prioritĂ©.
Voici quelques exemples courts pour illustrer la chose.
/* Globale versus locale */
String name = "Steve";
void main() {
String name = "Angelica";
name = "Naomi";
System.out.println(name);
}
Quelle variable est modifiée à la ligne 7? locale ou globale?
La variable locale, déclarée à la ligne 6, car elle a priorité sur la variable globale.
Quel nom s'affiche? Naomi ou Steve?
Naomi. La variable locale dans main masque la variable globale (qui nâest plus accessible dans main Ă cause de ce masquage).
/* Locale versus locale */
void main() {
String name = "Angelica";
System.out.println(rename(name));
System.out.println(name);
}
String rename(String name) {
name = "Demonica";
return name;
}
Qu'est-ce qui s'affiche Ă la ligne 5?
Demonica. Câest la valeur de retour de rename.
Qu'est-ce qui s'affiche Ă la ligne 6?
Angelica. Le paramĂštre name est locale Ă la mĂ©thode rename. Cette variable rĂ©coit la valeur de la variable dans main comme argument. Par contre, ce paramĂštre (locale Ă rename) nâexiste plus aprĂšs le retour de la mĂ©thode. rename retourne la nouvelle valeur, mais la variable name dans main ne la reçoit pas. La valeur de retour passe plutĂŽt directement dans un print. Alors la variable locale dans main nâa subit aucune modification du dĂ©but jusquâĂ la fin.
Quelques exemples dâerreur (de conflit) de portĂ©e
Variable inaccessible
void isolated() {
int answer = 7;
}
void main() {
System.out.println(answer); // erreur "cannot find symbol"
}
Ici, answer est locale Ă la mĂ©thode isolated, alors il nâest pas visible dans main, contrairement Ă si cette variable avait Ă©tĂ© dĂ©clarĂ©e globalement, Ă lâextĂ©rieure dâune mĂ©thode.
int answer = 7; // déclaration globale
void main() {
System.out.println(answer); // answer est visible
}
Déclaration dupliquée
String thing(String t) {
String t = t + "2"; // erreur "duplicate local variable"
return t;
}
void main() {
System.out.println(thing("thing"));
}
Ici, dans la mĂ©thode thing on dĂ©clare dĂ©jĂ un paramĂštre String t. Alors quand on dĂ©clare une autre variable locale du mĂȘme nom Ă la ligne 2, Java nous indique une erreur. Si lâintention Ă©tait de simplement modifier la valeur reçue dans le paramĂštre alors on peut réécrire la ligne 2 comme ceci :
String thing(String t) {
t = t + "2"; // référence valide au paramÚtre t déjà déclarée
return t;
}
void main() {
System.out.println(thing("thing"));
}
La diffĂ©rence est que la ligne 2 nâest plus une dĂ©claration dâune nouvelle variable. Elle est dĂ©sormais une rĂ©fĂ©rence Ă la variable dĂ©jĂ dĂ©clarĂ©e dans la liste de paramĂštres.
Exercices
đ Tester la comprĂ©hension
Faire les deux questions de choix multiples au dĂ©but de la page ici pour vĂ©rifier votre comprĂ©hension de la portĂ©e des variables. Ne faites pas les problĂšmes de programmation car ils intĂšgrent dâautres concepts que nous ne verrons pas dans ce cours.
La raison que les exercices de programmation sur la page sont dĂ©conseillĂ©s est quâils sollicitent des concepts de la programmation orientĂ©e objet que nous nâavons pas appris. Ce sont plutĂŽt des concepts du cours ICS4U.
Je vous suggÚre plutÎt les exercices pratiques suivants qui sont mieux adaptés à notre contexte.
đ ïž Pratique
Travaillez dans le répertoire GitHub partagé par votre enseignant pour la pratique et les exercices.
Cette pratique vise Ă dĂ©montrer les diffĂ©rences entre une approche de variables globales et une approche de variables locales dans un cas oĂč les deux sont des choix valides.
Le contexte est lâutilisation dâun symbole spĂ©cifique comme indicateur dâinvite de rĂ©ponses chaque fois quâon pose une question Ă lâutilisateur. On veut que ce symbole soit facile Ă changer si on veut utiliser un autre symbole. On veut aussi que le symbole soit utilisĂ© dans plusieurs mĂ©thodes.
Approche avec variable globale
Avec cette approche, on dĂ©clare une variable globale pour le symbole. Par la suite nous concatenons ce symbole Ă la fin de chaque question posĂ©e Ă lâutilisateur. Pour montrer lâutilitĂ© Ă travers plusieurs mĂ©thodes, chaque question se trouve dans sa propre mĂ©thode.
Le Scanner de la console est également déclaré comme variable globale pour un accÚs direct pour toutes les méthodes.

Fichier
GlobalVar.java
import java.util.*;
final Scanner CONSOLE = new Scanner(System.in);
final String PROMPT = " > ";
void main() {
String name = getName();
int age = getAge();
System.out.println("Votre nom est " + name + " et vous avez " + age + " ans.");
}
String getName(){
System.out.print("Quel est votre prénom?" + PROMPT);
String name = CONSOLE.next();
CONSOLE.nextLine(); //vider le reste de la ligne
return name;
}
int getAge() {
System.out.print("Quel est votre Ăąge?" + PROMPT);
int age = CONSOLE.nextInt();
CONSOLE.nextLine();
return age;
}
- Copiez ce code dans un fichier
GlobalVar.javaet lâexĂ©cuter pour voir comment il fonctionne. - Ajouter un commentaire aprĂšs chaque dĂ©claration de variable pour indiquer sâil sâagit dâune variable locale ou globale. Les variables sont
CONSOLE,PROMPT;name,age;name;age. - Modifiez la valeur de
PROMPTpour utiliser un autre symbole que>. Lancez le programme de nouveau pour voir le changement. - Renommez les variables dans
mainet lancez le programme pour voir si ça change le fonctionnement. Selon vos observations, est-ce que la variable nommĂ©enamedansmainest le mĂȘme objet en mĂ©moire que la variable nommĂ©enamedansgetName?
Approche avec variables locales seulement
Avec cette approche, les variables Ă partager sont dĂ©clarĂ©es localement dans main et partagĂ© via le mĂ©canisme argument-paramĂštre. De plus, au lieu de crĂ©er une variable pour le symbole prompt, on crĂ©e une mĂ©thode. Parce que chaque mĂ©thode est visible par les autres dans le fichier, toutes les autres mĂ©thodes peuvent lâappeler.

Fichier
LocalVar.java
import java.util.*;
void main() {
Scanner console = new Scanner(System.in);
String name = getName(console);
int age = getAge(console);
System.out.println("Votre nom est " + name + " et vous avez " + age + " ans.");
}
void prompt(String question) {
System.out.print(question + " > ");
}
String getName(Scanner in) {
prompt("Quel est votre nom?");
String name = in.next();
in.nextLine(); // vider le reste de la ligne
return name;
}
int getAge(Scanner in) {
prompt("Quel est votre Ăąge?");
int age = in.nextInt();
in.nextLine();
return age;
}
- Copiez ce code dans un fichier
LocalVar.javaet lâexĂ©cuter pour voir comment il fonctionne. Confirmez quâil fonctionne - du point de vue de lâutilisateur - de maniĂšre identique ĂGlobalVar. - Modifiez le programme pour changer le symbole dâinvite de commande dans
prompt(). Est-ce que câĂ©tait plus facile ou difficile ou Ă©quivalent Ă ce quâil fallait faire la derniĂšre fois? - ĂnumĂ©rer les Ă©lĂ©ments que vous avez prĂ©fĂ©rez de la version
GlobalVaret les Ă©lĂ©ments que vous avez prĂ©fĂ©rez dansLocalVar. ĂnumĂ©rer aussi des Ă©lĂ©ments que vous nâavez pas aimĂ© dans les deux versions. Ajoutez ces listes dans un commentaire dâen-tĂȘte dans un troisiĂšme fichierPreferredVar.java. Combiner vos Ă©lĂ©ments prĂ©fĂ©rĂ©s de chaque version dans cette troisiĂšme version ou apporter des modifications pour crĂ©er votre propre approche. RĂ©soudre les erreurs de fusion et lancer ce troisiĂšme programme pour vĂ©rifier quâĂ la console lâexpĂ©rience reste identique pour lâutilisateur malgrĂ© les changements.
-
Il y a des nuances Ă âpartout dans un programmeâ, mais ces nuances ne sont pas importants dans ce cours. Pour votre curiositĂ©, voici quand mĂȘme un bref survol. Nos programmes tiennent dans un seul fichier .java, alors partout dans le fichier serait plus apte. Les fichiers .java reprĂ©sentent implicitement une classe Java. Alors partout dans la classe serait aussi plus prĂ©cis. Mais les variables Java peuvent ĂȘtre qualifiĂ©es de publiques ou privĂ©es. Les variables privĂ©es sont seulement âglobalesâ dans la classe, tandis que les variables publiques sont âglobalesâ pour tout un package de classes (Ă lâextĂ©rieur de la classe elle-mĂȘme). Ce concept sâĂ©tend Ă la portĂ©e des classes (publiques ou privĂ©es) dans les packages et la portĂ©e des packages (exportĂ©es ou non) dans des modules. â©