đ Membres statiques
Survol et attentes
Plusieurs mot-clĂ©s Java dans la signature classique public static void main(String[] args) ont maintenant Ă©tĂ© dĂ©mystifiĂ©s, Dâabord on a les types void et String[]. Plus rĂ©cemment on a vue public et private qui dĂ©terminent la visibilitĂ© dâune classe ou de ses membres Ă lâextĂ©rieur de la classe. Il ne reste que static Ă expliquer.
Définitions
- Membre dynamique
- Un membre dâune classe (attribut ou mĂ©thode) qui est associĂ© Ă une instance de la classe, soit aux objets créés et dĂ©truits durant lâexĂ©cution du programme.
- Membre statique
- Un membre dâune classe (attribut ou mĂ©thode) qui est associĂ© Ă la classe elle-mĂȘme et non aux objets créés Ă partir de la classe. Les membres statiques sont disponibles mĂȘme si aucun objet nâest créé. Ces membres sont dĂ©clarĂ©s avec le mot-clĂ©
static. - Classe utilitaire
- Une classe qui contient exclusivement des membres statiques pour effectuer des tùches spécifiques. Les membres statiques sont accessibles directement en utilisant le nom de la classe, comme avec les classes
MathetIntegerde Java. - ĂlĂ©ments statiques et dynamiques
- En gĂ©nĂ©ral, les parties dâun programme qui sont connues explicitement au moment de la compilation sont dites âstatiquesâ. Les autres Ă©lĂ©ments sont âdynamiquesâ, connus seulement au moment de lâexĂ©cution.
- Les déclarations de classes sont statiques.
- Les objets et les variables locales sont dynamiques.
- Dans certains langages oĂč les dĂ©finitions de fonctions et des variables peuvent exister en dehors des classes (la plupart des langages Ă part Java), ces fonctions et variables globales sont aussi statiques.
- Les langages de programmation qui exigent la dĂ©claration de types pour les variables et fonctions sont dits âstatiquement typĂ©sâ; les autres sont dits âdynamiquement typĂ©sâ car le type doit ĂȘtre dĂ©terminĂ© au moment de lâexĂ©cution.
Objectifs dâapprentissage
Ă la fin de cette leçon vous devrez ĂȘtre en mesure de :
- DĂ©crire la diffĂ©rence entre les membres statiques et dynamiques dâune classe.
- Distinguer lâutilisation dâun membre statique et lâutilisation dâun membre dynamique dans divers extraits de code, comme la dĂ©claration de membres dâune classe ou lâutilisation de ces membres dans un algorithme.
CritĂšres de succĂšs
- Je suis capable dâutiliser des membres statiques dans mes objets ou les membres statiques de plusieurs classes utilitaires de Java.
Dynamique versus statique
Dans la programmation, le terme âstatiqueâ fait rĂ©fĂ©rence au stade de compilation/interprĂ©tation du projet. Si les types sont connus au moment de la compilation, un langage de programmation est dit âstatiquement typĂ©â. Java et C++ sont des langages statiquement typĂ©s parce quâon doit dĂ©clarer les types des variables et fonctions dans le code. De mĂȘme, si des variables ou des mĂ©thodes opĂšrent directement sur la classe (et non sur une instance de la classe), elles sont dites âstatiquesâ parce que la dĂ©finition de la classe est connue au moment de la compilation, contrairement aux instances de la classe (les objets) qui sont crĂ©es durant lâexĂ©cution du programme.
De lâautre cĂŽtĂ©, tout ce qui est créé ou dĂ©terminĂ© au moment de lâexĂ©cution est dite âdynamiqueâ. Par exemple, les variables locales sont dynamiques parce quâelles sont créées et dĂ©truites Ă chaque fois que la mĂ©thode qui les contient est appelĂ©e. Les objets sont aussi dynamiques parce quâils sont créés et dĂ©truits durant lâexĂ©cution du programme. Dans certains langages, la dĂ©termination du type est aussi dynamique parce que le type nâest pas dĂ©clarĂ© dans la syntaxe du langage mais seulement dĂ©terminĂ© au moment de lâexĂ©cution en fonction de lâinformation contenue dans la variable. Python et Javascript sont des langages dynamiquement typĂ©s.
Le mot-clé static
En Java, le mot-clĂ© static sâapplique Ă un membre dâune classe pour lâassocier Ă la classe elle-mĂȘme et non aux instances de la classe. Cela signifie que les variables et les mĂ©thodes statiques sont disponibles mĂȘme si aucun objet nâest créé Ă partir de la classe.
On connaßt déjà quelques exemples notables dans la bibliothÚque standard de Java :
-
La classe
Mathcontient des méthodes et constantes (variablesfinal) statiques pour effectuer des opérations mathématiques. On les utilise en appelantMath.PIou par exemple,Math.sqrt(16). -
Les classes qui emballent les types primitifs (comme
Integer,Double, etc.) contiennent des méthodes statiques pour convertir des chaßnes de caractÚres en nombres commeInteger.parseInt("42")ou pour obtenir des informations fixes en lien avec le type, commeDouble.MAX_VALUE. -
La méthode
mainqui est le point dâentrĂ©e de tout programme Java. On ne dĂ©clare aucun objet pour utiliser notre programme, on passe seulement le nom de notre classe, p. ex. avec la commandejava App. La machine virtuelle Java peut alors appeler directement la mĂ©thode statique avec le nom de la classe, p. ex.App.main(args).
Classes utilitaires
Les exemples comme Math et Integer sont des classes contenant exclusivement des membres publiques statiques. Ce type de classe est souvent appelĂ© une âclasse utilitaireâ ou âclasse de serviceâ parce quâelle fournit des mĂ©thodes et des constantes pour effectuer des tĂąches spĂ©cifiques.
Dépendances statiques
Tout ce quâon ajoutait comme membre dans nos classes en ICS3U - Scanner et autres variables globales, mĂ©thodes pour la dĂ©composition - devaient ĂȘtre dĂ©clarĂ©s static pour satisfaire au compilateur. Câest parce que :
- la méthode
mainest statique et - on utilisait tout directement dans
mainsans dĂ©clarer dâobjet pour notre propre classe.
La mĂ©thode main Ă©tant static signifie quâelle ne peut pas accĂ©der Ă des membres non statiques de la classe car ils ne sont pas créés en mĂȘme temps que la mĂ©thode main lors de la compilation. Donc tout ce quâon voulait utiliser dans main devait aussi ĂȘtre static pour ĂȘtre accessible.
Classe ou tout est statique Ă cause de main
Cas typique de programme Java avant dâapprendre les objets. Tout est statique parce quâon lâutilise directement dans main sans crĂ©er dâobjet pour la classe.
public class Main {
static int x = 42;
static void doStuff() {
System.out.println("On bosse");
}
public static void main(String[] args) {
// utilise directement les attributs et méthodes statiques
System.out.println(x);
doStuff();
}
}
Classe avec main et un objet pour la classe
Cas hybride oĂč les fonctions âdĂ©finition dâun objetâ et âpilote du programmeâ sont accomplies par la mĂȘme classe : on a une mĂ©thode main mais aussi des attributs et mĂ©thodes dâobjet. Ce type de classe nâest pas souvent utilisĂ© non plus. On utilise plutĂŽt une classe pour dĂ©clarer des objets et une autre pour le pilote.
public class Main {
int x = 42;
void doStuff() {
System.out.println("On bosse");
}
public static void main(String[] args) {
// Crée un objet de la classe Main
Main m = new Main();
// utilise les attributs et méthodes de l'objet
System.out.println(m.x);
m.doStuff();
}
}
Mélanger des membres statiques et dynamiques
Il est possible quâune classe objet dĂ©clare quelques attributs ou mĂ©thodes statiques en plus de dĂ©clarer des attributs et mĂ©thodes pour les instances de la classe.
Lâexemple le plus courant est un attribut qui compte le nombre dâobjets créés Ă partir de la classe, ou qui assure lâassignation dâun numĂ©ro dâidentitĂ© unique Ă chaque objet, oĂč les deux.
- Cet attribut est déclaré
staticpour exister mĂȘme sâil nây a aucun objet. - On lâinitialise Ă 0 dans la dĂ©claration.
- On lâincrĂ©mente dans le constructeur de la classe qui est appelĂ© chaque fois quâun objet est créé.
- Si on le cache (visibilité
private), on ajoute un accesseur statique pour le lire.
Classe objet
public class Thing {
// variable de classe
private static int count = 0;
// variables d'instance
private String name;
private int id;
public Thing(String name) {
this.name = name;
this.id = count; // assigne un nombre unique Ă chaque objet
count++; // incrémente la variable de classe
}
// accesseur statique
public static int count() {
return count;
}
// ... accesseurs, mutateurs, etc. pour les variables d'instance
@Override
public String toString() {
return String.format("Thing %d s'appelle %s\n", id, name);
}
}
Classe pilote
public class Main {
public static void main(String[] args) {
Thing t1 = new Thing("Antoinette");
Thing t2 = new Thing("Berenice");
Thing t3 = new Thing("Constantin");
// appels de méthodes d'instance, sur les objets individuels
String rollCall = t1.toString() + t2.toString() + t3.toString();
System.out.println(rollCall);
// appelle statique, sur la classe Thing
System.out.printf("Il existe %d Thing.\n", Thing.count());
}
}
Voici le diagramme UML pour la classe Thing. Notez que le mot-clĂ© static est utilisĂ© dans le texte entre accolades pour indiquer les membres statiques et que dans lâimage, ces membres sont soulignĂ©s.
@startuml Thing
!theme amiga
class Thing {
- count = 0 : {static} int
- name : String
- id : int
+ Thing(String name)
+ count() : {static} int
+ toString() : String
}
@enduml
Exercices
Pratique
Ajustez le code de votre objet simple pour ajouter un compteur statique privĂ© ainsi quâun accesseur statique public pour ce compteur. Modifiez aussi le code dans la classe pilote pour afficher le nombre dâobjets créés.