Introduction à Java - les paquetages - Frédéric VOISIN FIIFO - « Remise à Niveau »
Les paquetages Les équivalents Java des « librairies », i.e. des classes qui « vont ensemble » : la hiérarchie java: java.lang, java.io, java.util, java.awt, java.rmi, … d’autres hiérarchies de paquetages: javax.*, org.*, sun.*, … Dans un même paquetage ? des composants « reliés » logiquement (fonctionnellement) des classes qui doivent être implémentées « en même temps » : elles ne sont pas indépendantes sans être (forcément) liées par une relation d’héritage ! un paquetage définit un niveau de visibilité supplémentaire : les classes d’un même paquetage peuvent accéder de façon sélective à certains composants, indépendamment de tout relation d’héritage. Ils permettent de gérer des « espaces de nommage »: Éviter des conflits de noms (importation et/ou nommage explicite) Structurer les bibliothèques de classes
Les paquetages (suite) On peut déclarer explicitement un paquetage de rattachement package dates; // ce qui suit appartient au paquetage dates ! // Convention : nom de paquetage en minuscules class RnDate {... } Attention: la déclaration de paquetage doit alors être la première instruction du fichier ! Il existe un paquetage par défaut, si on n’en indique pas explicitement le paquetage « anonyme » C’est celui qu’on a utilisé jusqu’à présent pour toutes nos classes : toutes nos classes appartenaient au même paquetage. Un paquetage peut avoir des sous-paquetages package dates.gregorien ; Il faudra respecter une correspondance entre la structure en paquetages et l’arborescence des fichiers… Attention aussi à la variable CLASSPATH !
Paquetages et espace de nommage On peut toujours identifier une classe (publique) en la préfixant par son nom de paquetage java.util.ArrayList L = new java.util.ArrayList(); dates.RnDate maDate = new date.RnDate(); Par défaut, son nom simple n’est utilisable qu’à l’intérieur de son paquetage package dates; // on se place dans le paquetage dates ! ... RnDate maDate = new RnDate(); Les règles importations sont là pour autoriser la notation abrégée: import java.util.ArrayList; // importe la classe ArrayList ArrayList L = new ArrayList(); // autorisé: notation abrégée java.util.ArrayList L = new java.util.ArrayList(); // reste OK ! import java.util.*; // importe toutes les classes de java.util // n’importe pas les sous-paquetages !
Paquetages et espace de nommage (suite) Si on gère mal les importations, on peut avoir des conflits de noms qu’on résout par la notation qualifiée (explicite) : import paquetage1.*; // définit une classe maClasse import paquetage2.*; // définit une classe maClasse maClasse C = new maClasse(); // ambigu => refusé par le compilateur paquetage1.maClasse C = new paquetage1.maClasse(); // OK ! Par convention, toutes les classes et sous-paquetages de java.lang sont implicitement importés. Ne pas confondre directives d’importation Java et « include » à la C : « import » fournit une facilité d’abréviation pour les noms des classes Retrouver la description de la classe relève de la gestion du CLASSPATH !
Paquetage et visibilité Si on ne spécifie pas un niveau de visibilité explicite (public, private, protected), un membre est visible à l’intérieur de son paquetage, que ce soit dans le même fichier ou non (visibilité « paquetage » ou « friend » par analogie avec C++) = c’est la visibilité par défaut ! Pour une classe, les seules visibilités sont public et « paquetage ». Par défaut une classe n’est donc visible que dans son paquetage. La visibilité protected est moins restrictive que « paquetage » : un champ protected est visible dans tout le paquetage indépendamment des relations d’héritage. Pour qu’un champ soit visible, sa classe doit elle-même l’être…
Paquetage et visibilité (suite) Attention: on ne peut pas interdire que quelqu’un se place dans un paquetage donné, et donc bénéficie de la visibilité « paquetage » (et protected!). Pour vraiment encapsuler un champ, il faut le déclarer private. Champs private : on peut prévoir des méthodes public / protected ou encore « paquetage » pour y accéder en contrôlant l’usage qui en est fait (ex: contrôler la valeur mise dans un champ). Ne pas confondre règles de visibilité (qui a le droit de voir quoi) et règles d’importation (comment nomme-t-on la classe)
Exemple: Tableau des visibilités package p2; import p1.A; class B extends A { … } class E{…} paquetage p2 package p1; public class A { public int pub; protected int prot; int paq; private int priv; } package p1; class C { … } package p1; class D extends A {…} paquetage p1
Exemple (suite) : Tableau des visibilités pub prot paq priv class A OK class B class C class D class E D’après « Java et Internet: Concepts et Programmation », G. Roussel et E. Duris, Vuibert, 2000
Paquetages et structuration en fichiers (rappels) Il doit y avoir une correspondance entre le découpage en paquetages et l’organisation en répertoires des fichiers Permet de retrouver dynamiquement le fichier qui contient le bytecode d’une classe Important pour le téléchargement de classes ! A l’exécution, la classe de nom pack1.pack2.maClasse doit se trouver dans une sous-arborescence se terminant par pack1/pack2/MaClasse.class (sous Unix) ou dans une archive .jar. Le tout est relatif au contenu de la variable CLASSPATH qui précise les répertoires à parcourir… ;-( Pas toujours évident de savoir où on trouve une classe ;-( pas toujours évident de savoir si les autres trouveront bien la même classe (même problème que pour le PATH Unix !)
Paquetages et structuration en fichiers (suite) Attention : au plus une unité (classe, interface) publique par fichier ! Un paquetage peut être éclaté sur plusieurs fichiers et peut contenir plusieurs unités publiques et des unités non publiques. Un fichier .class par unité (publique ou non) Convention: pour avoir un nom de paquetage réellement unique, on le préfixe par son nom de domaine Internet renversé… Important pour les paquetages mis à disposition sur le réseau et partagé ! ex: com.sun.image.codec.jpeg On peut regrouper un ensemble de fichiers .class dans un fichier d’archive suffixé par .jar et créé par le gestionnaire d’archives jar. Un tel fichier d’archive peut aussi être mis dans la variable CLASSPATH