4.
Graphisme 2D et concepts de
programmation objet
Ce chapitre examine les principaux mécanismes de dessins en deux
dimensions (2D) de Java et approfondit les concepts de programmation
objet suivants : sous-classe, interface, variables de classe et d’objet, méthode
de classe et d’objet.
4.1 Dessin avec les classes Graphics et une sous-
classe de JFrame
Étudions d’abord un exemple de programme qui dessine un bonhomme
simple dans une fenêtre.
Exemple. JavaPasAPas/chapitre_4/
ExempleDessin2DDansJFrame.java
Le programme ExempleDessin2DDansJFrame.java dessine un bonhomme
simple (appelons-le Bot) dans une fenêtre produite par la classe
javax.swing.JFrame.
import java.awt.*;
import javax.swing.JFrame;
public class ExempleDessin2DDansJFrame extends JFrame {
public ExempleDessin2DDansJFrame() {
super("Exemples de dessin avec les méthodes de Graphics");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
// La méthode paint() est appelée automatiquement lors de la création
// du JFrame
// La méthode paint() fait un dessin d'un bonhomme
public void paint(Graphics g) {
// Il faut appeler la méthode paint() de la super-classe
super.paint(g);
g.setColor(Color.green);
g.fillOval(100, 100, 200, 200); // La tête
g.setColor(Color.black);
g.fillRect(150, 150, 20, 20); // L'oeil gauche
g.fillRect(230, 150, 20, 20); // L'oeil droit
g.drawLine(150, 250, 250, 250); // La bouche
108
g.setColor(Color.red);
g.fillRect(100, 300, 200, 200); // Le corps
}
public static void main(String args[]) {
new ExempleDessin2DDansJFrame();
}
}
Voici le résultat de l’exécution du programme :
Le dessin est effectué dans une fenêtre graphique qui correspond à un espace
à deux dimensions (2D) illustré à la figure suivante. L’axe des x est l’axe
horizontal et l’axe des y, le vertical. Par opposition à la convention
mathématique usuelle, l’axe des y est orienté vers le bas. Les figures
graphiques font référence aux coordonnées de cet espace.
109
0 100 150 200 230 300 x
0
100
(150,150) (230,150)
20
150
200
(150,250) (250,250)
250
300
400
500
Figure 17. Coordonnées du Bonhomme.
Certains aspects sembleront flous à ce point-ci et seront détaillés par la suite.
La clause import java.awt.* apparaît en début de programme étant donné que
les classes java.awt.Graphics et java.awt.Color sont utilisées. Le * permet
d’importer toutes les classes du package java.awt sans devoir spécifier
chacune des classes individuellement.
import java.awt.*;
La méthode main() ne fait que créer un objet de la classe
ExempleDessin2DDansJFrame par :
new ExempleDessin2DDansJFrame();
110
Cet objet représente la fenêtre dans laquelle est effectué le dessin.
• Notion de sous-classe
La classe ExempleDessin2DDansJFrame est une sous-classe de la classe
JFrame. Ceci est exprimé par la clause extends JFrame dans la ligne suivante.
public class ExempleDessin2DDansJFrame extends JFrame {
Inversement, on dit que JFrame est la super-classe de
ExempleDessin2DDansJFrame. La figure suivante montre un diagramme de
classe UML qui illustre ce concept. Un tel diagramme est utile pour
comprendre l’organisation des classes d’un programme Java. Chacune des
classes est représentée par un rectangle. Le nom de la classe apparaît dans la
partie supérieure, et les méthodes de la classe dans la partie inférieure. La
flèche représente une relation de sous-classe (aussi appelée relation d’héritage
ou encore de généralisation/spécialisation). À noter que le diagramme est partiel.
La classe JFrame contient beaucoup plus de méthodes et elle est elle-
même sous-classe d’une autre classe.
JFrame
JFrame()
setSize()
setVisible()
setDefaultCloseOperation()
paint()
...
ExempleDessin2DDansJFrame
main()
paint()
Figure 18. Représentation d’une sous-classe en UML.
En définissant une classe X comme une sous-classe d’une autre classe Y, la
classe X hérite de toutes les méthodes définies dans la classe Y. Ainsi, en
définissant la classe ExempleDessin2DDansJFrame comme une sous-classe de
JFrame à l’aide de l’utilisation de la directive extends, la classe
ExempleDessin2DDansJFrame hérite d’un ensemble de méthodes définies
dans la classe JFrame pour la manipulation des fenêtres. Ceci entraîne qu’un
objet de la classe ExempleDessin2DDansJFrame est aussi considéré comme un
objet de la super-classe JFrame. Il s’agit d’un exemple de ce que nous
111
appelons parfois du polymorphisme : une instance de la classe
ExempleDessin2DDansJFrame est aussi une instance de la classe JFrame ce
qui implique qu’une classe peut prendre plusieurs formes (littéralement : poly
[plusieurs] morph [forme]). Une sous-classe est parfois appelée une « classe
héritée » ou une « classe dérivée ».
Dans le diagramme, on ne répète pas les méthodes héritées dans la sous-
classe. Ceci est implicite. Les méthodes d’objet héritées de la classe JFrame
peuvent être appelées sur un objet de la classe ExempleDessin2DDansJFrame
comme si elles y avaient été définies. Le mécanisme d’héritage permet ainsi
de réutiliser les méthodes de la classe JFrame dans la classe
ExempleDessin2DDansJFrame sans avoir à les répéter. En particulier, dans
notre exemple, les méthodes setDefaultCloseOperation(), setSize(), setVisible(),
paint() sont héritées de la classe JFrame mais elles sont utilisées sur un objet
de la sous-classe ExempleDessin2DDansJFrame dans notre exemple. Cette
manière de programmer en créant une sous-classe d’une classe existante en
réutilisant le code d’une classe existante tout en ajoutant un comportement
plus spécialisé est une approche typique et très puissante de la
programmation objet. Dans notre exemple, ceci nous permet de créer des
fenêtres contenant des dessins d’une manière très simple sans avoir à en
programmer tous les détails.
Rappelons la syntaxe de la création d’un objet :
appel de constructeur d'objet :
new nomDeClasse ( liste des paramètres )
Ainsi, le new ExempleDessin2DDansJFrame() dans la méthode main() crée un
objet de la classe ExempleDessin2DDansJFrame. Concrètement, le new appelle
une méthode dite constructeur d’objet qui doit porter le même nom que celui
de la classe.
Dans notre exemple, le new ExempleDessin2DDansJFrame() provoque l’appel
de la méthode ExempleDessin2DDansJFrame() qui est une méthode constructeur
d’objet de la classe ExempleDessin2DDansJFrame. Le corps de la méthode
constructeur est utilisé pour initialiser certains aspects d’un objet au moment
de sa création.
La ligne suivante déclare le constructeur d’objet :
112
public ExempleDessin2DDansJFrame() {
La ligne suivante spécifie un titre qui apparaît dans le haut de la fenêtre.
super("Exemples de méthodes de Graphics dans un JFrame");
L’identificateur réservé super signifie d’appeler la méthode constructeur
correspondante de la super-classe JFrame. La méthode correspondante est
le constructeur de la super-classe qui a les mêmes paramètres. Il y a donc,
dans la classe JFrame, une méthode constructeur qui prend un titre
(String) en paramètre. Cette manière d’appeler le constructeur d’une super-
classe permet, dans une sous-classe, de compléter le travail du constructeur
de la super-classe en ajoutant des aspects particuliers à la sous-classe.
La ligne suivante spécifie qu’il faut terminer le programme (provoque un
appel de System.exit(0)) lorsque l’utilisateur clique dans le X dans le coin
supérieur droit de la fenêtre. Ceci est spécifié par l’appel de méthode d’objet
setDefaultCloseOperation(int operation) de la classe JFrame.
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
Identificateur réservé this
L’identificateur réservé this représente une référence à l’objet « ceci » qui est
en processus de construction par le constructeur. Comme cet objet est en
phase de construction, il ne peut y avoir une variable qui contient cet objet
pour y faire référence. Le this est un identificateur réservé qui permet de
désigner l’objet en phase de construction.
Le constructeur ne construit qu’un objet à la fois et il n’y a donc pas
d’ambigüité au sujet de l’objet représenté par this. Lorsqu’un appel de
méthode est fait sans spécifier un objet en préfixe, c’est comme si on mettait
le this en préfixe. Le this n’est donc pas obligatoire. Dans notre exemple, on
pourrait remplacer this.setDefaultCloseOperation(EXIT_ON_CLOSE) par
setDefaultCloseOperation(EXIT_ON_CLOSE). Cependant, dans certains cas,
il faut mettre le this pour éviter certaines ambiguïtés. Nous y reviendrons.
113
Voici le diagramme de syntaxe d’un appel de méthode d’objet tenant compte
de ces deux nouvelles possibilités. Rappelons qu’une méthode d’objet est
une méthode qu’on appelle sur un objet.
appel de méthode d'objet :
objet . nomDeMéthode ( liste des paramètres )
this
La méthode setSize() spécifie la largeur (400) et la hauteur (600) de la fenêtre :
this.setSize(400,600);
La méthode setVisible() rend la fenêtre visible. Ceci provoque indirectement
l’appel de la méthode paint(Graphics g) qui effectue le dessin.
this.setVisible(true);
Le dessin du Bot est alors effectué par la méthode paint().
La méthode paint() et le multifenêtrage
L’appel à paint() n’est pas visible dans notre programme. Cet appel se passe
au niveau de la super-classe JFrame. Le fait de ne pas voir les détails de cet
appel est un aspect un peu surprenant de la programmation Java, surtout
pour un novice. En fait, la méthode paint() est appelée automatiquement à
chaque fois qu’il faut redessiner le contenu de la fenêtre. Ceci est nécessaire
lorsqu’une partie cachée de la fenêtre est rendue visible au premier plan lors
de la manipulation des fenêtres par l’utilisateur. Plusieurs opérations de
manipulation de fenêtre conduisent à cette circonstance.
Donc, à chaque fois qu’on utilise la classe JFrame, la méthode paint() est
employée pour afficher quelque chose à l’intérieur de la fenêtre. D’autres
façons de procéder seront vues plus loin.
Regardons maintenant le détail de la méthode paint() qui effectue le dessin.
La méthode est déclarée par :
public void paint (Graphics g) {
114
Dans notre code, cette méthode est une méthode d’objet de la classe
ExempleDessin2DDansJFrame.
Rappelons le sens des identificateurs réservés public void :
• public signifie que la méthode peut être appelée de partout
• void signifie que la méthode ne retourne rien
L’absence de l’identificateur réservé static signifie que c’est une méthode
d’objet.
Cette méthode existe déjà dans la super-classe ! Cependant, la méthode de la
super-classe doit être redéfinie pour effectuer le dessin. Cette manière
d’adapter une classe en définissant une sous-classe qui redéfinit quelques
méthodes de la super-classe afin de spécialiser le comportement de la sous-
classe est typique de la programmation objet.
La méthode paint() a un paramètre appelé g dont le type est la classe
java.awt.Graphics. Rappelons que le nom de paramètre est précisé par le
programmeur et n’a pas d’importance d’un point de vue de l’exécution du
programme. Ce nom de paramètre est utilisé dans le corps de la méthode
pour désigner le paramètre. Le type du paramètre (Graphics) représente
un espace 2D de dessin qui fait partie de la fenêtre. Un tel objet de la classe
Graphics est appelé un contexte graphique. Les opérations de dessin dans la
méthode paint() seront effectuées en appelant des méthodes d’objet de l’objet
g. Lorsque la méthode paint() est appelée (on ne voit pas l’appel ici), l’objet
Graphics de la fenêtre est passé en paramètre à la méthode paint(). Comme
on ne voit pas l’appel à la méthode paint(), le programmeur curieux peut se
sentir dans un état un peu flou … Comment est créé l’objet Graphics ?
Qui appelle paint() ?
La méthode paint() de la classe ExempleDessin2DDansJFrame appelle tout
d’abord la méthode paint() de la super-classe JFrame. Notez la syntaxe
spéciale super.paint(). Par convention Java, l’usage du préfixe super désigne la
méthode de même nom et paramètres de la super-classe. L’appel à la
méthode paint() de la super-classe est une convention préétablie des classes
d’interface graphique de Java, car la méthode paint() de la super-classe
115
effectue certaines opérations nécessaires au bon fonctionnement de fenêtres
à structure complexe tel qu’une fenêtre JFrame.
// Il faut appeler la méthode paint() de la super-classe
super.paint(g);
Redéfinition d’une méthode par spécialisation et surcharge
dynamique
Après avoir appelé le paint() de la super-classe, le paint() de la sous-classe
ajoute les opérations de dessin. De ce point de vue la méthode paint() de la
sous-classe est une spécialisation de la méthode paint() de la super-classe. On
dit que la méthode paint() de la sous-classe ExempleDessin2DDansJFrame est
une redéfinition de la méthode paint() de la super-classe JFrame par
spécialisation de la méthode de la super-classe. Le résultat est qu’il y a
plusieurs méthodes paint() avec le même nom et les mêmes paramètres !
Comment savoir quelle méthode doit être appelée ? Java détermine la
méthode appropriée en fonction du type de l’objet qui est désigné pour
l’appel de la méthode. Si c’est un objet de la classe JFrame, c’est le paint()
de JFrame qui est appelé. Si c’est un objet de la classe
ExempleDessin2DDansJFrame , c’est le paint() de ExempleDessin2DDansJFrame
qui est appelé. Ce principe est appelé surcharge dynamique (ou encore
polymorphisme dynamique) d’un nom de méthode.
Identificateur réservé super
Lorsqu’une sous-classe redéfinie une méthode d’une super-classe, la syntaxe
super.nomMéthode() désigne l’appel de la méthode nomMéthode() de la super-
classe. Dans le cas d’un constructeur, il suffit d’utiliser super tout court pour
désigner le constructeur correspondant de la super-classe, c’est-à-dire celui
qui a les mêmes paramètres.
Voyons maintenant les méthodes de dessin. La ligne suivante spécifie que la
couleur courante de dessin sera le vert.
g.setColor(Color.green);
La méthode setColor(Color c) est une méthode d’objet de la classe
Graphics qui fixe la couleur utilisée pour les méthodes de dessin. Le
paramètre Color.green est un objet de la classe Color qui correspond à une
116
constante de classe définie dans la classe Color pour représenter la couleur
verte. La notion de constante de classe sera détaillée par la suite. La classe
Color inclut plusieurs autres constantes pour définir les principales
couleurs.
La ligne suivante dessine le cercle vert de la tête du bonhomme.
g.fillOval(100,100,200,200); // La tête
La méthode fillOval(int x, int y, int width, int height) dessine un
ovale plein inscrit dans un rectangle dont la coordonnée du coin supérieur
droit est (x, y) la largeur est width et la hauteur est height. Comme la hauteur
est égale à la largeur, ceci produit un cercle. La couleur employée est celle qui
a été prédéterminée par l’appel précédent à setColor().
La ligne suivante établit la couleur noire comme couleur courante.
g.setColor(Color.black);
La ligne suivante dessine un carré noir qui correspond l’œil gauche. Les
paramètres de fillRect(int x, int y, int width, int height) ont la
même signification que pour fillOval(). Comme la hauteur est égale à la
largeur, ceci produit un carré.
g.fillRect(150,150,20,20); // L'oeil gauche
La ligne suivante dessine l’œil droit.
g.fillRect(230,150,20,20); // L'oeil droit
La ligne suivante dessine une ligne qui correspond à la bouche.
g.drawLine(150,250,250,250); // La bouche
La méthode drawLine(int x1, int y1, int x2, int y2) dessine une
ligne qui part de la coordonnées (x1, y1) et se termine à la coordonnée (x2,
y2).
Ensuite, les deux lignes suivantes dessinent le rectangle rouge du corps.
g.setColor(Color.red);
g.fillRect(100,300,200,200); // Le corps
117
La classe Graphics contient plusieurs autres méthodes de dessin de
formes de base.
Exercice. En vous inspirant de l’exemple précédent, écrivez un programme
qui dessine un bonhomme de votre cru ou encore le bonhomme Iti suivant.
La taille de la fenêtre de Iti est 300 par 300.
Solution. JavaPasAPas/chapitre_4/ExerciceDessinIti.java
import java.awt.*;
import javax.swing.JFrame;
public class ExerciceDessinIti extends JFrame {
public ExerciceDessinIti() {
super("Dessin de Iti");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(300, 300);
this.setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
// Dessin de Iti
// La tête
g.setColor(Color.pink);
g.fillOval(133, 50, 33, 50);
// Le sourire
g.setColor(Color.black);
g.drawArc(133, 34, 33, 50, -125, 70);
// Les yeux
g.fillOval(138, 66, 8, 8);
g.fillOval(154, 66, 8, 8);
118
// Le corps
g.drawLine(150, 100, 150, 200);
// Les bras
g.drawLine(100, 100, 150, 150);
g.drawLine(200, 100, 150, 150);
// Les jambes
g.drawLine(100, 250, 150, 200);
g.drawLine(200, 250, 150, 200);
}
public static void main(String args[]) {
new ExerciceDessinIti();
}
}
• Création de plusieurs objets (fenêtres de dessin)
L’exemple suivant créé trois fenêtres qui correspondent à trois objets de la
classe ExempleDessin2DDansJFrame.
Exemple. Création de trois fenêtres de dessin.
import java.awt.*;
import javax.swing.JFrame;
public class ExempleDessin2DDansJFrame extends JFrame {
public ExempleDessin2DDansJFrame() {
super("Exemples de dessin avec les méthodes de Graphics");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400,600);
this.setVisible(true);
}
// La méthode paint() est appelée automatiquement lors de la création du JFrame
// La méthode paint() fait un dessin d'un bonhomme
public void paint (Graphics g) {
super.paint(g);
g.setColor(Color.green);
g.fillOval(100,100,200,200); // La tête
g.setColor(Color.black);
g.fillRect(150,150,20,20); // L'oeil gauche
g.fillRect(230,150,20,20); // L'oeil droit
g.drawLine(150,250,250,250); // La bouche
g.setColor(Color.red);
g.fillRect(100,300,200,200); // Le corps
}
public static void main (String args[]) {
new ExempleDessin2DDansJFrame();
new ExempleDessin2DDansJFrame();
new ExempleDessin2DDansJFrame();
}
}
119
Chaque appel à new ExempleDessin2DDansJFrame() crée une nouvelle fenêtre.
NB Si vous exécutez ce programme, les fenêtres sont superposées. Il faut les
déplacer pour voir les trois.
4.2 Simplification du programme par une méthode
avec paramètres
Cette section approfondit la création de méthode et l’utilisation des
paramètres en montrant comment l’utilisation d’une méthode avec
paramètre peut grandement simplifier un programme et ceci dans le contexte
du dessin 2D. La notion de passage des paramètres sera étudiée en même
temps.
L’ exercice suivant permet de motiver l’utilisation d’une méthode avec
paramètres.
Exercice. Dessiner deux bonhommes de taille et position différentes tel
qu’illustré par la figure suivante :
Solution. JavaPasAPas/chapitre_4/Exercice2Bots.java
import java.awt.*;
import javax.swing.*;
public class Exercice2Bots extends JFrame {
public Exercice2Bots() {
super("Dessiner deux Bots");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
120
public void paint(Graphics g) {
super.paint(g);
// Le premier Bot
g.setColor(Color.green);
g.fillOval(100, 100, 200, 200); // La tête
g.setColor(Color.black);
g.fillRect(150, 150, 20, 20); // L'oeil gauche
g.fillRect(230, 150, 20, 20); // L'oeil droit
g.drawLine(150, 250, 250, 250); // La bouche
g.setColor(Color.red);
g.fillRect(100, 300, 200, 200); // Le corps
// Le deuxième Bot
g.setColor(Color.green);
g.fillOval(25, 50, 100, 100); // La tête
g.setColor(Color.black);
g.fillRect(50, 75, 10, 10); // L'oeil gauche
g.fillRect(90, 75, 10, 10); // L'oeil droit
g.drawLine(50, 125, 100, 125); // La bouche
g.setColor(Color.red);
g.fillRect(25, 150, 100, 100); // Le corps
}
public static void main(String args[]) {
new Exercice2Bots();
}
}
La solution précédente rappelle les mêmes méthodes deux fois. Pour la
position et la taille du Bot, il faut calculer de nouvelles valeurs des paramètres
à chaque fois. Une manière plus élégante de traiter ce problème consiste à
chercher une solution plus générale au dessin d’un Bot où sa position et sa
taille sont variables. Une technique souvent employée en graphisme 2D
consiste à définir un rectangle englobant à l’intérieur duquel sera dessiné le
Bot tel qu’illustré à la figure suivante. Le Bot est dessiné à l’échelle à l’intérieur
du rectangle. Comme pour la méthode fillRect(), quatre variables sont définies
121
pour représenter le rectangle englobant : les coordonnées x et y du coin
inférieur droit, la largeur et la hauteur du rectangle englobant.
Exemple.
0 x
0
(x,y)
largeur
(x+largeur/4,y+hauteur/8) (x+largeur*3/4-largeur/10,y+hauteur/8)
largeur/10
(x+largeur/4,y+hauteur*3/8) (x+largeur*3/4,y+hauteur*3/8)
hauteur
JavaPasAPas/chapitre_4/ExempleBotRectangleEnglobant.java
La version suivante dessine le même Bot que notre premier exemple mais en
utilisant des variables qui représentent le rectangle englobant.
import java.awt.*;
import javax.swing.JFrame;
public class ExempleBotRectangleEnglobant extends JFrame {
public ExempleBotRectangleEnglobant() {
super("Bot avec rectangle englobant");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
int x = 100;
int y = 100;
int largeur = 200;
int hauteur = 400;
122
// Bonhomme à l'échelle dans un rectangle englobant défini
// par x,y,largeur,hauteur
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public static void main(String args[]) {
new ExempleBotRectangleEnglobant();
}
}
Exemple. JavaPasAPas/chapiter_5/
Exemple2BotsRectangleEnglobant.java
On peut maintenant facilement redessiner le Bot deux fois en changeant la
position et la taille par la modification des valeurs des variables x, y, largeur et
hauteur mais en répétant exactement les mêmes instructions deux fois.
import java.awt.*;
import javax.swing.JFrame;
public class ExempleBotRectangleEnglobant extends JFrame {
public ExempleBotRectangleEnglobant() {
super("Bot avec rectangle englobant");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
123
public void paint(Graphics g) {
super.paint(g);
int x = 100;
int y = 100;
int largeur = 200;
int hauteur = 400;
// Bonhomme à l'échelle dans un rectangle englobant défini
// par x,y,largeur,hauteur
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public static void main(String args[]) {
new ExempleBotRectangleEnglobant();
}
}
Cette solution oblige de répéter deux fois les mêmes énoncés. On peut éviter
cette répétition en les regroupant dans une méthode et en appelant cette
méthode à deux reprises.
Exemple. JavaPasAPas/chapitre_4/ExempleMethodePaintBot.java
Dans l’exemple suivant la méthode paintBot(Graphics g, int x, int y, int
largeur, int hauteur) regroupe les énoncés de dessin du Bot. Plutôt que de
répéter ces énoncés deux fois, il suffit d’appeler la méthode deux fois !
124
import java.awt.*;
import javax.swing.JFrame;
public class ExempleMethodePaintBot extends JFrame {
public ExempleMethodePaintBot() {
super("2 Bots avec méthode paintBot()");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
// Méthode qui dessine un Bot dans un objet Graphics g
// à l'échelle dans un rectangle englobant de paramètres
// x,y,largeur,hauteur
public static void paintBot(Graphics g, int x, int y, int largeur, int hauteur) {
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public void paint(Graphics g) {
super.paint(g);
// Dessin du premier Bot
paintBot(g, 100, 100, 200, 400);
// Dessin du deuxième Bot
paintBot(g, 25, 50, 100, 200);
}
public static void main(String args[]) {
new ExempleMethodePaintBot();
}
}
La ligne suivante dans le code de l’exemple est une déclaration de la signature
de la méthode paintBot(). Cette déclaration est similaire à celle de la méthode
main() :
public static void paintBot (Graphics g, int x, int y, int
largeur, int hauteur) {
125
Signature d’une méthode
La signature d’une méthode précise :
- le nom de la méthode
- la forme des paramètres
- la forme du résultat
La signature d’une méthode permet de déterminer comment appeler la
méthode.
La méthode paintBot() fait partie de la classe ExempleMethodePaintBot car elle
est déclarée dans le corps de la classe, c’est-à-dire entre les accolades qui
suivent le nom de la classe. Dans cet exemple, on aurait aussi bien pu en faire
une méthode d’objet en omettant le static. Nous reviendrons sur cet aspect.
La liste des paramètres entre virgules spécifie le type et le nom de chacun des
paramètres. Le programmeur décide des noms, types et nombre des
paramètres. Cette liste de paramètres qui apparaît dans la déclaration de la
signature de la méthode représente les paramètres dits formels. D’autre part,
lorsqu’on appelle la méthode, on doit spécifier les paramètres dits réels.
Dans le corps de la méthode, les énoncés font référence aux noms des
paramètres formels comme s’ils étaient des variables. Par exemple, dans la
ligne suivante, les variables x, y, largeur et hauteur sont les paramètres formels
de la méthode paintBot() :
g.fillOval(x,y,largeur,hauteur/2); // La tête
Pour dessiner les deux Bot, la méthode paint() appelle deux fois la méthode
paintBot() en précisant les paramètres réels. La ligne suivante est le premier
appel.
paintBot(g, 100, 100, 200, 400);
126
Les paramètres g, 100, 100, 200, 400 sont les paramètres réels. Il est à noter
qu’un paramètre réel n’est pas nécessairement une constante. Ce peut aussi
être un nom de variable, de paramètre, et même une expression. Lors de
l’appel de la méthode, on peut imaginer que la valeur du paramètre réel est
en quelque sorte affectée à la variable qui correspond au paramètre formel.
Ensuite, la méthode est exécutée.
paintBot(g, 100, 100, 200, 400)
paintBot (Graphics g, int x, int y, int largeur, int hauteur)
On obtient ainsi exactement le même effet que si l’on avait effectué la
séquence suivante qui dessine le premier Bot dans
Exemple2BotsRectangleEnglobant :
int x = 100;
int y = 100;
int largeur = 200;
int hauteur = 400;
// Bonhomme à l'échelle dans un rectangle englobant défini par x,y,largeur,hauteur
g.setColor(Color.green);
g.fillOval(x,y,largeur,hauteur/2); // La tête
g.setColor(Color.black);
g.fillRect(x+largeur/4,y+hauteur/8,largeur/10,hauteur/20); // L'oeil gauche
g.fillRect(x+largeur*3/4-largeur/10,y+hauteur/8,largeur/10,hauteur/20); // L'oeil droit
g.drawLine(x+largeur/4,y+hauteur*3/8,x+largeur*3/4,y+hauteur*3/8); // La bouche
g.setColor(Color.red);
g.fillRect(x,y+hauteur/2,largeur,hauteur/2); // Le corps
Passage de paramètre par valeur ou par référence
Le fait de copier la valeur du paramètre réel en l’affectant au paramètre
formel correspond au concept de passage de paramètre par valeur. Ainsi,
dans la méthode, si la valeur du paramètre formel est modifiée, ceci n’affecte
pas le paramètre réel. En Java, c’est la seule manière de passer un paramètre
lorsqu’il s’agit d’un type primitif (int, double, etc.). D’autres langages offrent
une autre option : le passage de paramètre par référence qui permet de
modifier la valeur du paramètre réel. Dans le cas d’un paramètre objet en
Java, la valeur passée est la référence à l’objet.
Pour le paramètre g, le contexte graphique (objet de la classe Graphics) de
paint() est tout simplement passé à la méthode paintBot() qui va donc dessiner
127
sur le même contexte graphique que si le dessin avait été effectué
directement dans paint(). À noter que le nom du paramètre réel g est ici le
même que celui du paramètre formel. Ceci n’est pas obligatoire. Par exemple,
on aurait pu définir la méthode paintBot() de la manière suivante sans que cela
n’ait d’effet sur le comportement du programme.
public static void paintBot (Graphics unGraphics, int x, int y, int largeur, int hauteur) {
unGraphics.setColor(Color.green);
unGraphics.fillOval(x,y,largeur,hauteur/2); // La tête
unGraphics.setColor(Color.black);
unGraphics.fillRect(x+largeur/4,y+hauteur/8,largeur/10,hauteur/20); // L'oeil gauche
unGraphics.fillRect(x+largeur*3/4-largeur/10,y+hauteur/8,largeur/10,hauteur/20); // L'oeil droit
unGraphics.drawLine(x+largeur/4,y+hauteur*3/8,x+largeur*3/4,y+hauteur*3/8); // La bouche
unGraphics.setColor(Color.red);
unGraphics.fillRect(x,y+hauteur/2,largeur,hauteur/2); // Le corps
}
Le nom en soi du paramètre formel n’a pas d’importance. L’important c’est
de respecter l’ordre et le type des paramètres lors de l’appel.
Même si le passage de paramètre est par valeur, c’est-à-dire qu’une copie de
la référence à l’objet graphique g est passée à la méthode, la méthode peut
modifier le contenu de l’objet en appelant les méthodes de modification de
l’objet.
Raccourci pour l’appel d’une méthode de la même classe
La méthode paintBot() est une méthode de classe. Rappelons que l’appel
d’une méthode de classe débute normalement par le nom de la classe. Dans
le cas présent, il n’est pas nécessaire de mettre le nom de classe car la
méthode appelée fait partie de la même classe que la méthode appelante. Ce
raccourci est permis lorsqu’une méthode en appelle une autre de la même
classe.
En considérant cette nouvelle possibilité, la syntaxe d’un appel de méthode
de classe est donc :
appel de méthode de classe :
nomDeClasse . nomDeMéthode ( liste des paramètres )
128
Exercice. Reprenez l’exemple de méthode avec votre bonhomme (ou le Iti).
Définissez une méthode paintXXX (Graphics g, int x, int y, int largeur, int hauteur)
qui dessine votre bonhomme et appelez-la à deux reprises avec des valeurs
différentes pour les paramètres.
Solution avec Iti :
JavaPasAPas/chapitre_4/ExerciceMethodePaintIti.java
import java.awt.*;
import javax.swing.JFrame;
public class ExerciceMethodePaintIti extends JFrame {
public ExerciceMethodePaintIti() {
super("2 Itis avec méthode paintIti()");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
// Méthode qui dessine un Iti dans un objet Graphics g
// à l'échelle dans un rectangle englobant de paramètres x,y,largeur,hauteur
public static void paintIti(Graphics g, int x, int y, int largeur, int hauteur) {
// Coordonnées du milieu du rectangle englobant pour faciliter les calculs
int milieux = x + largeur / 2;
int milieuy = y + hauteur / 2;
g.setColor(Color.pink); // La tête
g.fillOval(x + largeur / 3, y, largeur / 3, hauteur / 4);
g.setColor(Color.black); // Le sourire
g.drawArc(x + largeur / 3, y - hauteur / 12, largeur / 3, hauteur / 4, -125, 70);
g.fillOval(milieux - largeur / 8, y + hauteur / 12, largeur / 12, hauteur / 24); // Les yeux
g.fillOval(milieux + largeur / 8 - largeur / 12, y + hauteur / 12, largeur / 12, hauteur / 24);
g.drawLine(milieux, y + hauteur / 4, milieux, y + hauteur * 3 / 4); // Le corps
g.drawLine(x, y + hauteur / 4, milieux, milieuy); // Les bras
g.drawLine(x + largeur, y + hauteur / 4, milieux, milieuy);
g.drawLine(x, y + hauteur, milieux, y + hauteur * 3 / 4); // Les jambes
g.drawLine(x + largeur, y + hauteur, milieux, y + hauteur * 3 / 4);
}
public void paint(Graphics g) {
super.paint(g);
// Dessin du premier Bot
paintIti(g, 100, 100, 200, 400);
// Dessin du deuxième Bot
paintIti(g, 25, 50, 100, 200);
}
public static void main(String args[]) {
new ExerciceMethodePaintIti();
}
}
129
Résultat :
Exercice. Dessiner plusieurs bonhommes Bot et Iti dans la même fenêtre.
Solution. JavaPasAPas/chapitre_4/ExercicePlusieursBotEtIti.java
import java.awt.*;
import javax.swing.JFrame;
public class ExercicePlusieursBotEtIti extends JFrame {
public ExercicePlusieursBotEtIti() {
super("Rassemblement de Bots et Itis");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
// Méthode qui dessine un Bot dans un objet Graphics g
// à l'échelle dans un rectangle englobant de paramètres x,y,largeur,hauteur
public static void paintBot(Graphics g, int x, int y, int largeur, int hauteur) {
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
// Méthode qui dessine un Iti dans un objet Graphics g
// à l'échelle dans un rectangle englobant de paramètres x,y,largeur,hauteur
public static void paintIti(Graphics g, int x, int y, int largeur, int hauteur) {
// Coordonn�es du milieu du rectangle englobant pour faciliter les calculs
130
int milieux = x + largeur / 2;
int milieuy = y + hauteur / 2;
// La tête
g.setColor(Color.pink);
g.fillOval(x + largeur / 3, y, largeur / 3, hauteur / 4);
// Le sourire
g.setColor(Color.black);
g.drawArc(x + largeur / 3, y - hauteur / 12, largeur / 3, hauteur / 4, -125, 70);
// Les yeux
g.fillOval(milieux - largeur / 8, y + hauteur / 12, largeur / 12, hauteur / 24);
g.fillOval(milieux + largeur / 8 - largeur / 12, y + hauteur / 12, largeur / 12, hauteur / 24);
// Le corps
g.drawLine(milieux, y + hauteur / 4, milieux, y + hauteur * 3 / 4);
// Les bras
g.drawLine(x, y + hauteur / 4, milieux, milieuy);
g.drawLine(x + largeur, y + hauteur / 4, milieux, milieuy);
// Les jambes
g.drawLine(x, y + hauteur, milieux, y + hauteur * 3 / 4);
g.drawLine(x + largeur, y + hauteur, milieux, y + hauteur * 3 / 4);
}
public void paint(Graphics g) {
super.paint(g);
paintBot(g, 10, 40, 50, 100);
paintBot(g, 200, 200, 20, 40);
paintBot(g, 150, 500, 50, 25);
paintBot(g, 300, 50, 40, 160);
paintIti(g, 150, 200, 40, 80);
paintIti(g, 50, 350, 100, 200);
paintIti(g, 300, 300, 60, 120);
}
public static void main(String args[]) {
new ExercicePlusieursBotEtIti();
}
}
Résultat :
131
4.3 Traitement des événements de souris (interface
MouseListener)
Dans les applications interactives, il faut pouvoir détecter les actions de
l’utilisateur (déplacement de la souris, click de la souris, touche de clavier,
etc.) et y réagir. Le package java.awt inclut les mécanismes à cet effet.
Exemple. JavaPasAPas/chapitre_4/ExempleEvenementSouris.java
Le programme suivant illustre les mécanismes de base de détection des
actions de la souris. Le programme répond à un click de la souris (bouton de
gauche enfoncé avec Windows) en déplaçant le Bot à la position du click. La
position du click est déterminée par la position du curseur de souris au
moment où le bouton est enfoncé.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExempleEvenementSouris extends JFrame implements MouseListener {
// Variables d'objet qui contiennent les coordonnées de la souris
// Le premier sera dessiné à la coordodonnée (0,0)
private static int x = 0; // Coordodonnée x du Bot à dessiner
private static int y = 0; // Coordodonnée y du Bot à dessiner
public ExempleEvenementSouris() {
super("Exemple de traitement d'événements de la souris");
// Le paramètre this de addMouseListener() indique que l'objet qui doit
// réagir aux événements de souris est l'objet
// qui est créé par ce constructeur
addMouseListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
// méthode d'objet de la classe ExempleEvenementSouris qui est
// appelée si le bouton de souris est enfoncé
public void mousePressed(MouseEvent leMouseEvent) {
x = leMouseEvent.getX(); // place la coordodonnée x de la souris dans la variable x
y = leMouseEvent.getY(); // place la coordodonnée y de la souris dans la variable y
// repaint() provoque un nouvel appel à paint()
repaint();
}
// Il faut absolument définir les autres méthodes pour les autres
// événements de souris même s'ils ne font rien
public void mouseClicked(MouseEvent leMouseEvent) {}
public void mouseEntered(MouseEvent leMouseEvent) {}
public void mouseExited(MouseEvent leMouseEvent) {}
public void mouseReleased(MouseEvent leMouseEvent) {}
132
public static void paintBot(Graphics g, int x, int y, int largeur, int hauteur) {
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public void paint(Graphics g) {
super.paint(g);
paintBot(g, x, y, 50, 100);
}
public static void main(String args[]) {
new ExempleEvenementSouris();
}
}
Chaque fois que l’utilisateur emploie la souris, ceci produit un événement (event)
d’interface à l’utilisateur. Un événement d’interface à l’utilisateur est le résultat
d’une action de l’utilisateur sur un périphérique d’entrée tel que la souris ou
le clavier. Pour réagir à l’événement, il faut programmer une méthode qui
sera automatiquement activée lorsque l’événement est détecté. Cette
méthode doit avoir une signature prédéfinie (par exemple,
mousePressed(MouseEvent e)) pour un événement correspondant à
enfoncer le bouton de la souris). Elle doit être incluse dans la classe d’un
objet qui est désigné par le programmeur comme écouteur (listener) de
l’événement.
Dans notre exemple, l’objet écouteur est l’objet de la classe
ExempleEvenementSouris qui représente une fenêtre JFrame. La ligne
suivante du constructeur désigne this comme écouteur des événements de la
souris. L’identificateur réservé this représente une référence à l’objet de la
classe ExempleEvenementSouris qui est construit par le constructeur.
addMouseListener(this);
133
• Notion d’interface Java
Il faut que la classe de l’objet écouteur implémente des méthodes
particulières pour répondre aux différents événements de la souris. Ceci est
représenté par le fait que la classe de l’objet écouteur (ExempleEvenementSouris)
doit implémenter l’interface java.awt.event.MouseListener. Ceci est
spécifié dans la ligne suivante par la clause implements MouseListener dans la
déclaration de la classe :
public class ExempleEvenementSouris extends JFrame implements
MouseListener
Mettre en œuvre l’interface java.awt.event.MouseListener signifie que la classe
doit contenir la définition d’un certain nombre de méthodes dont les
signatures sont précisées dans l’interface Java désignée par le nom
java.awt.event.MouseListener.
Qu’est-ce qu’une interface au sens de Java? Une interface Java est
simplement un squelette de classe au sens où une interface contient la
définition d’un ensemble de signatures de méthodes mais sans
nécessairement spécifier le corps de la méthode. Par exemple, l’interface
java.awt.event.MouseListener est définie de la manière suivante :
package java.awt.event;
public abstract interface MouseListener extends java.util.EventListener
{
public abstract void mouseClicked(java.awt.event.MouseEvent e){}
public abstract void mousePressed(java.awt.event.MouseEvent e){}
public abstract void mouseReleased(java.awt.event.MouseEvent e){}
public abstract void mouseEntered(java.awt.event.MouseEvent e){}
public abstract void mouseExited(java.awt.event.MouseEvent e){}
}
Les méthodes de l’interface (mouseClicked(), mousePressed(), …) ont un corps
vide. Il est prévu que le corps de ces méthodes soit précisé dans la classe qui
implémente l’interface.
Comme elle implémente l’interface java.awt.event.MouseListener
(clause implements java.awt.event.MouseListener), la classe ExempleEvenementSouris
doit contenir toutes ces méthodes. Ainsi en forçant une classe à implémenter
une interface, la classe est contrainte à fournir les méthodes de cette interface.
Cette manière de contraindre une classe à répondre à des méthodes garantit
que la classe sera en mesure de fournir une réponse lors de l’exécution du
134
programme. Le rôle des méthodes de l’interface
java.awt.event.MouseListener est de spécifier comment réagir aux
différents événements de la souris. En forçant un écouteur d’événement de
souris à implémenter l’interface java.awt.event.MouseListener, il est
garanti que l’objet écouteur puisse répondre aux différents événements de la
souris. La souris peut générer plusieurs sortes d’événements tel que : bouton
enfoncé, bouton cliqué, bouton relâché, curseur de souris déplacé hors des
limites de la fenêtre, etc. Pour réagir à chacune des sortes d’événements, il
faut définir la méthode correspondante de l’interface MouseListener. Par
exemple, pour réagir à l’enfoncement du bouton de la souris, il faut définir
la méthode mousePressed(MouseEvent e) dans la classe de
l’écouteur ExempleEvenementSouris. Ces méthodes seront appelées
automatiquement lorsque les événements se produisent.
Voici la méthode dans notre exemple :
public void mousePressed(MouseEvent leMouseEvent){
x = leMouseEvent.getX(); // place la coordonnée x de la souris dans la variable x
y = leMouseEvent.getY(); // place la coordonnée y de la souris dans la variable y
// repaint() provoque un nouvel appel à paint()
repaint();
}
La méthode a un paramètre qui est un objet de la classe MouseEvent. Cet
objet contient des informations au sujet de l’événement de souris. La
méthode d’objet getX() de MouseEvent retourne la coordonnée x du
curseur au moment où le bouton de la souris est enfoncé et la méthode
getY(), la coordonnée y. Ces coordonnées sont employées dans notre
programme afin de pouvoir dessiner un Bot à cet endroit.
Ensuite, la méthode repaint() est appelée. Cette méthode est héritée de la
classe JFrame qui est la super-classe de ExempleEvenementSouris. Elle
provoque automatiquement un appel à paint() qui dessine un nouveau Bot à
la position courante de la souris.
135
Méthodes paint(), repaint() et update()
Pourquoi ne devrait-on pas appeler paint() directement ? Ceci est dû au fait
que la gestion de l’affichage est en réalité un processus complexe dans un
contexte à multifenêtrage comme c’est le cas avec un système d’exploitation
tel que Windows. Pour s’assurer que tout se passe correctement, il faut une
coordination avec les autres événements des autres fenêtres. Il est prévu que
la méthode repaint() effectue cette coordination avant que paint() ne soit
appelée. En particulier, la méthode repaint() appelle la méthode update() qui
efface le contenu du contexte graphique en rétablissant la couleur de fond et
elle appelle paint() par la suite. D’autre part, c’est la méthode repaint() qui est
appelée automatiquement lorsqu’il faut redessiner le contenu de la fenêtre
lors des manipulations des fenêtres.
Les autres méthodes de l’interface MouseListener sont vides dans notre
exemple car il n’y a rien à faire pour ces autres sortes d’événements :
public void mouseClicked(MouseEvent leMouseEvent){}
public void mouseEntered(MouseEvent leMouseEvent){}
public void mouseExited(MouseEvent leMouseEvent){}
public void mouseReleased(MouseEvent leMouseEvent){}
Elles doivent tout de même être déclarées dans la classe
ExempleEvenementSouris car elle implémente l’interface MouseListener.
Nous verrons plus loin qu’il est possible d’éviter ces déclarations vides en
employant une classe Adaptor.
Un peu comme pour la méthode paint(), cette manière de répondre aux
événements peut sembler un peu mystérieuse car on ne voit nulle part l’appel
aux méthodes de réponse à l’événement. Il faut comprendre que tout le code
de gestion des événements se trouve en quelque part dans du code hérité de
la super-classe JFrame et qu’il serait compliqué d’expliquer le détail de la
gestion d’événement à ce point-ci.
• Variables déclarées au niveau de la classe
Vous avez peut-être noté que les variables x et y ne sont pas définies dans la
méthode mousePressed() mais au début du corps de la classe dans les lignes
suivantes :
private int x = 0; // Coordonnée x du Bot à dessiner
private int y = 0; // Coordonnée y du Bot à dessiner
136
On appelle parfois ces variables des attributs de la classe. En Java, les attributs
peuvent avoir différents degrés de visibilité indiqué par un terme tel que
public, private ou protected. Si aucun de ces termes qualifiant la visibilité précède
la déclaration de la variable, alors cette variable a une visibilité par défaut ce
qui signifie que la variable est accessible par toutes les classes dans le même
package, mais par seulement ces classes. Le terme protected signifie que
l’attribut est accessible par toutes les classes dans le même package mais aussi
par les classes dérivées. Le terme public signifie que l’attribut est librement
accessible. Le private signifie que ces variables ne peuvent être accédées à
partir des autres classes. Les méthodes d’une classe ont la même notion de
visibilité : nous avons déjà vu que la méthode main d’un programme doit
avoir la visibilité public.
Dans notre exemple, les variables sont des variables d’objet de la classe
ExempleEvenementSouris. L’emploi de variables d’objet permet à ces variables
d’être accédées non seulement dans mousePressed() mais aussi dans la méthode
paint() :
public void paint (Graphics g) {
super.paint(g);
paintBot(g,x,y,50,100);
}
L’utilisation de variables d’objet permet d’accéder aux mêmes variables dans
les deux méthodes. Ainsi des données peuvent être partagées entre
méthodes d’objet de la même classe. Si on avait déclaré les variables
localement dans la méthode mousePressed(), la méthode paint() n’aurait pu y
accéder. D’ailleurs, ceci aurait provoqué une erreur de compilation.
Exemple. Si vous compilez le programme suivant, vous obtiendrez une
erreur de compilation indiquant que x et y n’existe pas dans paint() :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExempleVariablesLocalesErreur extends JFrame implements MouseListener {
public ExempleVariablesLocalesErreur() {
super("Exemple de traitement d'événements de la souris");
137
// Le paramètre this de addMouseListener() indique que l'objet qui doit
// réagir aux événements de souris est l'objet
// qui est créé par ce constructeur
addMouseListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
// Méthode d'objet de la classe ExempleEvenementSouris qui est
// appelée si le bouton de souris est enfoncé
public void mousePressed(MouseEvent leMouseEvent) {
int x = leMouseEvent.getX(); // place la coordonnée x de la souris dans la variable x
int y = leMouseEvent.getY(); // place la coordonnée y de la souris dans la variable y
// repaint() provoque un nouvel appel à paint()
repaint();
}
// Il faut absolument définir les autres méthodes pour les autres
// événements de souris même s'il ne font rien
public void mouseClicked(MouseEvent leMouseEvent) {}
public void mouseEntered(MouseEvent leMouseEvent) {}
public void mouseExited(MouseEvent leMouseEvent) {}
public void mouseReleased(MouseEvent leMouseEvent) {}
public static void paintBot(Graphics g, int x, int y, int largeur, int hauteur) {
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public void paint(Graphics g) {
super.paint(g);
paintBot(g, x, y, 50, 100);
}
public static void main(String args[]) {
new ExempleVariablesLocalesErreur();
}
}
138
L’erreur de compilation vient du fait qu’une variable déclarée localement
dans une méthode ne peut être accédée dans une autre méthode.
Portée d’une variable, variable locale
La portée d’une variable déclarée dans une méthode est limitée au corps de la
méthode. En d’autres mots, la variable déclarée dans une méthode est locale
à la méthode.
Concrètement, ceci signifie que la variable disparaît en quelque sorte lorsque
l’exécution de la méthode est terminée. Il serait possible de déclarer des
variables x et y dans chacune des deux méthodes, mousePressed() et paint(), mais
ceci n’aurait pas produit le résultat recherché car ces variables seraient en
réalité des variables différentes même si elles portent le même nom !
Pour que le contenu d’une variable soit accessible à plusieurs méthodes de la
même classe, il faut que la variable soit déclarée de manière globale au niveau
de classe. D’autre part, une variable déclarée au niveau de la classe peut-être
soit une variable de classe ou une variable d’objet.
Variable de classe (static)
L’identificateur réservé static indique que c’est une variable de classe. Quand
la mention static est omise, on dit parfois qu’il s’agit d’une variable d’instance
ou variable d’objet.
Dans l’exemple précédent, nous avons employé des variables d’objet. Mais,
on aurait aussi bien pu les définir comme des variables de classe sans que
cela n’affecte le comportement de l’exemple puisqu’il n’y a qu’un seul objet
de la classe ExempleEvenementSouris.
Exercice. Ajoutez l’identificateur réservé static dans la déclaration des
variables x et y de ExempleEvenementSouris et faites exécuter le programme.
private static int x = 0; // Coordonnée x du Bot à dessiner
private static int y = 0; // Coordonnée y du Bot à dessiner
Dans le contexte de cet exemple, le résultat est le même que si les variables
étaient des variables d’objet. Voyons maintenant un cas où l’emploi d’une
variable de classe ou d’objet ne produit pas le même effet parce qu’il y a plus
d’un objet de la même classe.
139
Différence entre variable d’objet et variable de classe
Il y a une différence importante entre variable d’objet (ou variable d’instance)
et variable de classe. Il n’y a qu’une valeur pour une variable de classe peu
importe le nombre d’objets de la classe. Ceci signifie que tous les objets de
la classe partagent la même variable. Dans le cas d’une variable d’objet, il y a
en quelque sorte une variable différente pour chacun des objets.
Pour voir la différence entre variable d’objet et de classe, il faut créer au
moins deux objets de la classe ExempleEvenementSouris, c’est-à-dire deux
fenêtres.
Exemple. JavaPasAPas/chapitre_4/
ExempleEvenementSouris2Fenetres.java
L’exemple suivant illustre l’effet de l’utilisation de variables de classe dans le
cas de plusieurs objets de la même classe.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExempleEvenementSouris2Fenetres extends JFrame implements MouseListener {
// Variables de classe x et y
private static int x = 0; // Coordonnée x du Bot à dessiner
private static int y = 0; // Coordonnée y du Bot à dessiner
public ExempleEvenementSouris2Fenetres() {
super("Exemple de traitement d'événements de la souris");
// Le paramètre this de addMouseListener() indique que l'objet qui doit
// réagir aux événements de souris est l'objet
// qui est créé par ce constructeur
addMouseListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 600);
this.setVisible(true);
}
// Méthode d'objet de la classe ExempleEvenementSouris qui est
// appelée si le bouton de souris est enfoncé
public void mousePressed(MouseEvent leMouseEvent) {
x = leMouseEvent.getX(); // place la Coordonnée x de la souris dans la variable x
y = leMouseEvent.getY(); // place la Coordonnée y de la souris dans la variable y
// repaint() provoque un nouvel appel à paint()
repaint();
}
// Il faut absolument définir les autres méthodes pour les autres
// événements de souris même s'il ne font rien
public void mouseClicked(MouseEvent leMouseEvent) {}
140
public void mouseEntered(MouseEvent leMouseEvent) {}
public void mouseExited(MouseEvent leMouseEvent) {}
public void mouseReleased(MouseEvent leMouseEvent) {}
public static void paintBot(Graphics g, int x, int y, int largeur, int hauteur) {
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public void paint(Graphics g) {
super.paint(g);
paintBot(g, x, y, 50, 100);
g.drawString("x=" + x + " y=" + y, 10, 550);
}
public static void main(String args[]) {
new ExempleEvenementSouris2Fenetres();
new ExempleEvenementSouris2Fenetres();
}
}
La figure suivante montre les deux fenêtres dont le Bot a été positionné à
deux endroits différents en utilisant la souris. La ligne suivante a été ajoutée
à la méthode paint() pour afficher la valeur des variables x et y. La méthode
drawString(String str, int x, int y) a comme paramètres un
String à afficher et les coordonnées de l’emplacement où l’on veut afficher
ce String.
g.drawString("x="+x+" y="+y,10,550);
Dans la figure suivante produite par l’exécution du programme, le Bot de la
fenêtre de gauche a été positionné avant celui de la fenêtre de droite. À ce
point-ci de l’exécution du programme, les variables de classe x et y
contiennent les coordonnées de Bot de la fenêtre de droite, soit x = 288 et y
=442, parce que le Bot de la fenêtre de droite a été positionné le dernier. Il
141
n’y a pas de valeurs spécifiques à chacun des objets ! Les deux objets
partagent la variable de classe.
Classe ExempleEvenementSouris2Fenetres
static int x = 288
static int y = 442
Objet laFenetre1 Objet laFenetre2
Figure 19. Variables de classe (static).
Si l’on réduit la fenêtre de gauche et on la réaffiche (le bouton de réduction
est celui qui contient une petite barre horizontale dans le coin supérieur droit
de la fenêtre), on obtient l’effet suivant :
Le Bot de la fenêtre de gauche est maintenant à la même position que celui
de la fenêtre de droite ! Mais, nous ne l’avons pas repositionné ! Ceci est dû
au fait qu’il n’y a qu’une seule valeur de x et y dans le cas de variables de
142
classe. Lorsque la fenêtre de gauche est réaffichée, ceci provoque un appel
automatique à la méthode paint() sur l’objet qui correspond à la fenêtre de
gauche. La méthode paint() accède aux coordonnées x et y afin d’afficher le
Bot. Mais comme, la valeur courante de x et y contient les coordonnées du
Bot de la fenêtre de droite (288, 442) parce qu’il a été positionné le dernier,
la méthode paint() dessine le Bot au même endroit dans la fenêtre de gauche.
• Variable d’objet
Pour que chacune des deux fenêtres ait ses propres valeurs des coordonnées
x et y du Bot, il faut en faire des variables d’objet. Dans ce cas, les deux objets
ont leurs propres variables x et y. L’appel à paint() peut ainsi employer les
valeurs de x et y particulières à l’objet.
Objet 1 Objet 2
int x = 62 int x = 288
int y = 84 int y = 442
Figure 20. Variables d’objet.
Exemple. JavaPasAPas/chapitre_4/ExempleVariableDobjet.java
Dans ExempleVariableDobjet, les coordonnées du Bot sont des variables
d’objet. Vous pouvez vérifier que le comportement des fenêtres est
maintenant correct. Chacune des fenêtres a ses propres valeurs de x et y pour
le Bot.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExempleVariableDobjet extends JFrame implements MouseListener {
// Variables d'objet qui contiennent les coordonnées de la souris
// Le premier sera dessiné à la coordonnée (0,0)
private int x = 0; // Coordonnée x du Bot é dessiner
private int y = 0; // Coordonnée y du Bot é dessiner
public ExempleVariableDobjet() {
super("Exemple de variable d'objet x et y");
// Le paramètre this de addMouseListener() indique que l'objet qui doit
// réagir aux événements de souris est l'objet
// qui est créé par ce constructeur
addMouseListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
143
this.setSize(400, 600);
this.setVisible(true);
}
// Méthode d'objet de la classe ExempleEvenementSouris qui est
// appelée si le bouton de souris est enfoncé
public void mousePressed(MouseEvent leMouseEvent) {
x = leMouseEvent.getX(); // place la coordonnée x de la souris dans la variable x
y = leMouseEvent.getY(); // place la coordonnée y de la souris dans la variable y
// repaint() provoque un nouvel appel é paint()
repaint();
}
// Il faut absolument définir les autres méthodes pour les autres
// événements de souris même s'il ne font rien
public void mouseClicked(MouseEvent leMouseEvent) {}
public void mouseEntered(MouseEvent leMouseEvent) {}
public void mouseExited(MouseEvent leMouseEvent) {}
public void mouseReleased(MouseEvent leMouseEvent) {}
public static void paintBot(Graphics g, int x, int y, int largeur, int hauteur) {
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public void paint(Graphics g) {
super.paint(g);
paintBot(g, x, y, 50, 100);
g.drawString("x=" + x + " y=" + y, 10, 550);
}
public static void main(String args[]) {
new ExempleVariableDobjet();
new ExempleVariableDobjet();
}
}
En conclusion, une variable de classe peut être employée si tous les objets
de la classe partagent la même valeur pour cette variable. Si chacun des objets
doit avoir sa propre valeur distincte pour la variable, il faut employer une
variable d’objet.
144
• Méthode d’objet ou de classe
Une distinction analogue existe entre les méthodes d’objet et de classe. Une
méthode de classe est appropriée lorsqu’elle n’utilise pas les variables d’objet.
En revanche, si la méthode utilise des variables d’objet, il faut en faire une
méthode d’objet.
Examinons le cas de la méthode paintBot() dans l’exemple précédent. C’est
une méthode de classe et ceci est correct car elle n’utilise pas directement les
variables d’objet x et y. En effet, elle utilise les paramètres x et y qui sont
passés par l’appel paintBot(g,x,y,50,100) dans la méthode paint().
public void paint (Graphics g) {
super.paint(g);
paintBot(g,x,y,50,100);
g.drawString("x="+x+" y="+y,10,550);
}
Dans paint(), les variables x et y correspondent aux variables d’objet. Les
valeurs des variables d’objet sont passées à la méthode de classe par l’appel
paintBot(g,x,y,50,100).
Regardons maintenant un autre exemple, où plutôt que de passer les valeurs
de x et y à paintBot() par les paramètres, la méthode paintBot() utilise
directement les variables d’objet x et y.
Exemple.
JavaPasAPas/chapitre_4/ExempleMethodeDobjetPaintBot.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExempleMethodeDobjetPaintBot extends JFrame implements MouseListener {
// Variables d'objet qui contiennent les coordonnées de la souris
// Le premier sera dessiné à la coordonnée (0,0)
private int x = 0; // Coordonnée x du Bot à dessiner
private int y = 0; // Coordonnée y du Bot à dessiner
public ExempleMethodeDobjetPaintBot() {
super("Exemple de traitement d'événements de la souris");
// Le paramètre this de addMouseListener() indique que l'objet qui doit
// réagir aux événements de souris est l'objet
// qui est créé par ce constructeur
addMouseListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
145
this.setSize(400, 600);
this.setVisible(true);
}
// Méthode d'objet de la classe ExempleEvenementSouris qui est
// appelée si le bouton de souris est enfoncé
public void mousePressed(MouseEvent leMouseEvent) {
x = leMouseEvent.getX(); // place la coordonnée x de la souris dans la variable x
y = leMouseEvent.getY(); // place la coordonnée y de la souris dans la variable y
// repaint() provoque un nouvel appel à paint()
repaint();
}
// Il faut absolument définir les autres méthodes pour les autres
// événements de souris méme s'il ne font rien
public void mouseClicked(MouseEvent leMouseEvent) {}
public void mouseEntered(MouseEvent leMouseEvent) {}
public void mouseExited(MouseEvent leMouseEvent) {}
public void mouseReleased(MouseEvent leMouseEvent) {}
public void paintBot(Graphics g, int largeur, int hauteur) {
// La méthode d'objet utilise directment les variables d'objet x et y
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public void paint(Graphics g) {
super.paint(g);
paintBot(g, 50, 100);
g.drawString("x=" + x + " y=" + y, 10, 550);
}
public static void main(String args[]) {
new ExempleMethodeDobjetPaintBot();
new ExempleMethodeDobjetPaintBot();
}
}
Dans cet exemple, la méthode d’objet paintBot() ne peut être une méthode
de classe car elle accède aux variables d’objet x et y. Si la méthode paintBot()
était déclarée static, une erreur de compilation serait signalée.
146
4.4 Constantes (final)
Lorsqu’il précède une variable, l’identificateur réservé final indique que la
variable ne peut être modifiée. Une telle variable désigne donc une constante
dans le programme Java. Une pratique souvent employée consiste à définir
les constantes utilisées dans un programme comme des variables final. Ceci
améliore la lisibilité du programme. D’autre part, si le programmeur doit
changer la valeur de la constante, il évite d’avoir à parcourir le programme
pour retrouver toutes les occurrences de la valeur constante pour la modifier.
Exemple. JavaPasAPas/chapitre_4/ExempleConstantesFinal.java
Dans l’exemple suivant qui reprend l’exemple précédent, la hauteur et la
largeur de la fenêtre sont définies comme des variables final. Ces constantes
sont employées dans le constructeur de fenêtre ExempleConstantesFinal() et la
méthode paint() pour ajuster la dimension du Bot et la position du message
affichée.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExempleConstantesFinal extends JFrame
implements MouseListener { // Constantes pour la taille de la fenetre
private static final int LARGEURFENETRE = 400;
private static final int HAUTEURFENETRE = 600;
// Variables d'objet qui contiennent les coordonnées de la souris
// Le premier sera dessiné à la coordonnée (0,0)
private int x = 0; // Coordonnée x du Bot à dessiner
private int y = 0; // Coordonnée y du Bot à dessiner
public ExempleConstantesFinal() {
super("Exemple de traitement d'événements de la souris");
// Le paramêtre this de addMouseListener() indique que l'objet qui doit
// réagir aux événements de souris est l'objet
// qui est créé par ce constructeur
addMouseListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(LARGEURFENETRE, HAUTEURFENETRE);
this.setVisible(true);
}
// Méthode d'objet de la classe ExempleEvenementSouris qui est
// appelée si le bouton de souris est enfoncé
public void mousePressed(MouseEvent leMouseEvent) {
x = leMouseEvent.getX(); // place la coordonnée x de la souris dans la variable x
y = leMouseEvent.getY(); // place la coordonnée y de la souris dans la variable y
// repaint() provoque un nouvel appel à paint()
repaint();
}
// Il faut absolument définir les autres méthodes pour les autres
147
// événements de souris même s'il ne font rien
public void mouseClicked(MouseEvent leMouseEvent) {}
public void mouseEntered(MouseEvent leMouseEvent) {}
public void mouseExited(MouseEvent leMouseEvent) {}
public void mouseReleased(MouseEvent leMouseEvent) {}
public void paintBot(Graphics g, int largeur, int hauteur) {
// La méthode d'objet utilise directment les variables d'objet x et y
g.setColor(Color.green);
g.fillOval(x, y, largeur, hauteur / 2); // La tête
g.setColor(Color.black);
g.fillRect(x + largeur / 4, y + hauteur / 8, largeur / 10, hauteur / 20); // L'oeil gauche
g.fillRect(
x + largeur * 3 / 4 - largeur / 10,
y + hauteur / 8,
largeur / 10,
hauteur / 20); // L'oeil droit
g.drawLine(
x + largeur / 4,
y + hauteur * 3 / 8,
x + largeur * 3 / 4,
y + hauteur * 3 / 8); // La bouche
g.setColor(Color.red);
g.fillRect(x, y + hauteur / 2, largeur, hauteur / 2); // Le corps
}
public void paint(Graphics g) {
super.paint(g);
paintBot(g, LARGEURFENETRE / 8, HAUTEURFENETRE / 6);
g.drawString("x=" + x + " y=" + y, 10, HAUTEURFENETRE - 50);
}
public static void main(String args[]) {
new ExempleConstantesFinal();
new ExempleConstantesFinal();
}
}
Exercice. Modifiez le programme précédent en définissant dans la classe
ExempleConstantesFinal deux constantes LARGEURBOT et
HAUTEURBOT qui seront utilisées dans l’appel à paintBot(). La valeur de
ces constantes sera calculée à partir des constantes LARGEURFENETRE
et HAUTEURFENETRE.
148
• Ensemble de constantes (types de données énumérés)
À noter que la constante Color.green qui représente une couleur de dessin
est en fait un nom de variable public static final de la classe Color. Il en est de
même pour les autres couleurs prédéfinies énumérées précédemment. Ainsi
cet ensemble des couleurs est un ensemble de constantes dans la classe
Color. Voici un extrait de la classe Color qui montre quelques déclarations
de couleurs. Une couleur est un objet de la classe Color créé avec le
constructeur Color(int r, int g, int b). Chacun des paramètres est un
entier entre 0 et 255 qui spécifie l’intensité d’une des trois composantes de la
couleur : rouge, vert et bleu. Cette manière de représenter les couleurs
correspond au système RGB.
public class Color
implements java.awt.Paint, java.io.Serializable
{
…
public static final java.awt.Color white = new Color(255,255,255);
public static final java.awt.Color lightGray = new Color(192,192,192);
public static final java.awt.Color gray = new Color(128,128,128);
public static final java.awt.Color darkGray = new Color(64,64,64);
public static final java.awt.Color black = new Color(0,0,0);
public static final java.awt.Color red = new Color(255,0,0);
public static final java.awt.Color pink = new Color(255,175,175);
public static final java.awt.Color orange = new Color(255,200,0);
public static final java.awt.Color yellow = new Color(255,255,0);
public static final java.awt.Color green = new Color(0,255,0);
public static final java.awt.Color magenta = new Color(255,0,255);
public static final java.awt.Color cyan = new Color(0,255,255);
public static final java.awt.Color blue = new Color(0,255,0);
// Constructeur de couleur
public void Color(int r, int g, int b)
{…
}
…
Pour accéder à une variable public d’une autre classe, il faut préfixer le nom
de la variable avec le nom de sa classe, d’où l’utilisation de la syntaxe
Color.green dans les exemples de programmes vus jusqu’à présent.
4.5 Sommaire d’une déclaration de classe
Résumons les concepts vus jusqu’à présent en portant un regard sommaire
au sujet de la déclaration d’une classe dont le diagramme syntaxique est le
suivant.
149
déclaration de classe :
class nomDeClasse relations corps de classe
modifieur
L’identificateur réservé class est optionnellement précédé d’une suite de
modifieurs. Nous n’avons rencontré que public dans le cas d’une classe. Le
sens des autres modifieurs sera expliqué ultérieurement.
modifieur :
public
private
static
final
etc.
Après le nom de classe, les relations avec d’autres classes sont spécifiées
(super-classe et interfaces à implémenter). Il ne peut y avoir qu’une seule
super-classe mais il peut y avoir plus d’une interface à implémenter. Lorsque
la clause extends est absente, par défaut, la classe est une sous-classe de
java.lang.Object qui est la racine de la hiérarchie des classes Java. Cette classe
contient des méthodes supportées par tous les objets. Par exemple, la
méthode getClass() de Object retourne la classe de l’objet.
relations :
extends nomDeClasse implements liste de noms d'interfaces
Ensuite, vient le corps de la classe qui contient les déclarations de ses
membres.
Membre d’une classe
Les variables et méthodes définies au niveau d’une classe sont appelées des
membres de cette classe.
150
corps de classe :
{ }
déclaration de membre
Le corps est une suite de déclarations de membres.
déclaration de membre :
déclaration de variable
déclaration de constructeur
déclaration de méthode
etc.
Voici la syntaxe pour chacun des types de membres.
déclarationDeVariable :
type nomDeVariable ;
modifieur = expression
,
déclaration de méthode :
type nomDeMéthode paramètres corps de méthode
modifieur
void
déclaration de constructeur :
nomDeClasse paramètres corps de constructeur
modifieur
paramètres :
( )
type nomParamètre
151
corps de méthode :
bloc d'énoncés
Le modifieur public pour un membre signifie qu’il peut être accédé de
l’extérieur de la classe par opposition à private. Le modifieur static spécifie qu’il
s’agit d’une variable ou méthode de classe. Une méthode de classe ne peut
accéder qu’aux variables de classe alors qu’une méthode d’objet peut accéder
aux variables de classes et d’objet tel qu’indiqué dans le tableau suivant :
Variable d’objet Variable de classe
Méthode de classe Accès interdit Accès permis
Méthode d’objet Accès permis Accès permis
Pour une variable, le modifieur final signifie qu’elle ne peut être modifiée
(constante).
• Portée des variables
Lorsqu’un nom de variable est employé dans le corps d’une méthode, ce
nom de variable peut correspondre à une des quatre possibilités suivantes :
• variable de classe
• variable d’objet
• variable locale
• paramètre formel
Lorsqu’une variable locale, disons v, est déclarée et qu’elle porte le même
nom qu’une variable de classe ou d’objet, le nom de variable v désigne la
variable locale. Ainsi, la variable locale masque en quelque sorte une variable
d’objet ou de classe du même nom. Pour désigner la variable de classe qui
est masquée, on peut employer la syntaxe nomClasse.v. Dans le cas d’une
méthode d’objet, la syntaxe this.v est aussi permise.
152
Exemple. JavaPasAPas/chapitre_4/ExempleVariablesLocales.java
Variable de classe masquée par une variable locale
public class ExempleVariablesLocales {
public static int x = 0;
public ExempleVariablesLocales() {}
public static void m1() {
int x = 1;
System.out.println("Valeur de la variable locale x dans la méthode de classe m1() =" + x);
System.out.println(
"Valeur de la variable de classe x dans la méthode de classe m1() ="
+ ExempleVariablesLocales.x);
}
public void m2() {
int x = 2;
System.out.println("Valeur de la variable locale x dans la méthode d'objet m2() =" + x);
System.out.println("Valeur de la variable de classe x dans la méthode d'objet m2() =" + this.x);
System.out.println(
"Valeur de la variable de classe x dans la méthode d'objet m2() ="
+ ExempleVariablesLocales.x);
}
public static void main(String args[]) {
System.out.println("Appel de la méthode de classe m1() :");
ExempleVariablesLocales.m1();
System.out.println("Création d'un objet :");
ExempleVariablesLocales unObjet = new ExempleVariablesLocales();
System.out.println("Appel de la méthode de d'objet m2() :");
unObjet.m2();
}
}
Résultat :
Appel de la méthode de classe m1() :
Valeur de la variable locale x dans la méthode de classe m1() =1
Valeur de la variable de classe x dans la méthode de classe m1() =0
Création d'un objet :
Appel de la méthode de d'objet m2() :
Valeur de la variable locale x dans la méthode d'objet m2() =2
Valeur de la variable de classe x dans la méthode d'objet m2() =0
Valeur de la variable de classe x dans la méthode d'objet m2() =0
153