Règles de visibilité en Java

           

Selon leur niveau de visibilité, les classes, les interfaces, les attributs et les méthodes peuvent être accessibles ou non depuis des classes du même paquetage ou depuis des classes d'autres paquetages. Si on tente de compiler une classe invoquant une classe, une interface ou un champ non accessible, il y a un message d'erreur pour indiquer que l'entité en question n'est pas accessible.

Les classes, attributs et méthodes peuvent être visibles ou non à l'intérieur d'autres paquetages ou d'autres classes.

Pour indiquer les degrés de visibilité, on utilise des modificateurs de visibilité. Les différents modificateurs sont indiqués par les mots clé :

Ces modificateurs sont indiqués devant l'en-tête d'une classe ou d'une méthode ou devant le type d'un attribut. Lorqu'il n'y a pas de modificateur, on dit que la visibilité est la visibilité par défaut.

Une classe ne peut que :

Un champ (attribut ou méthode) peut avoir les quatre degrés de visibilité.
On peut écrire par exemple :
    private int nbDonnees;
    public void methode() {}

Si un champ d'une classe A :

Ci-dessus, les niveaux de visibilité sont rangés par visibilité croissante.

Rappelons une règle : une méthode d'instance ne peut pas être redéfinie en diminuant son niveau de visibilité.

Les constantes et les prototypes de méthodes figurant dans une interface sont automatiquement publics et donc visibles de partout si l'interface est publique.

La quasi-totalité des attributs de la bibliothèque standard sont privés. Donner le statut privé à un attribut permet de garder un contrôle sur celui-ci et permet aussi de garder une cohérence entre les différents attributs.
Supposons qu'on veuille définir une classe CerclePositif pour un cercle dont le rayon, auquel correspond un attribut de type double nommé rayon, soit toujours positif ou nul ; on suppose que la classe possède aussi un attribut nommé diametre de type double qui doit toujours être égal au double du rayon. L'hypothèse du rayon non négatif faisant partie de la définition de la classe, il se peut que certaines méthodes de la classe utilisent cette hypothèse et ne fonctionnent plus correctement si le rayon se trouve être négatif ; il est aussi nécessaire que le changement du rayon s'accompagne du changement du diamètre (cohérence entre les attributs). On désire donc qu'un programme utilisant la classe CerclePositif ne puisse pas valuer le rayon sans qu'on contrôle sa modification (pour assurer la valeur positive du rayon et le fait que le diamètre soit e double du rayon) ; on peut alors décider de donner le statut privé à l'attribut rayon. On peut alors autoriser le changement de la valeur de rayon par l'intermédiaire d'une méthode nommée par exemple setRayon(double r) ; dans notre exemple, cette méthode contrôle le paramètre r pour donner la valeur r au rayon si r est positif et la valeur 0 sinon, et fait en sorte que le diamètre soit égal au double du rayon ; si on ne veut pas cacher la valeur de l'attribut rayon, on peut définir une méthode getRayon qui renvoie la valeur du rayon. De même pour le diamètre.
Des méthodes telles que getRayon et setRayon s'appellent des accesseurs ; on dira aussi que la méthode getRayon est un getter et que la méthode setRayon est un setter. La classe ci-dessous correspond à notre exemple ; on a muni aussi la classe d'un getter pour l'attribut diametre.

public class CerclePositif {
	private double rayon;
	private double diametre;

	public CerclePositif(double r) {
		if (r > 0) { 
                   rayon = r;
                   diametre = 2 * r;
           }
	}

	public double getRayon() {
		return rayon;
	}
	
	public void  setRayon( double  r) {
		if (r > 0) rayon = r;
		else rayon = 0;
		diametre = 2 * r;
	}

	public double getDiametre() {
		return diametre;
	}
}
D'une manière générale, nous conseillons de ne pas mélanger les langues dont sont issus les identificateurs que l'on définit ; si le choix est celui du français, tout identificateur est alors écrit totalement en français. Nous avons fait néanmoins une exception pour l'utilisation de get et set, car de nombreux identificateurs de méthodes de l'API (dont les noms sont bien sûr en anglais) sont construits selon cette syntaxe, et les autres choix, n'utilisant que le français, sont encore moins satisfaisants.

On peut distinguer différents usages d'un attribut privé :

 
Les fichiers suivants définissent des classes dans des paquetages. L'objectif est de mettre en évidence la visibilité des attributs selon les modificateurs de visibilité et selon que les classes se trouvent ou non dans un même paquetage. La visibilité pour les méthodes est identique à celle des attributs.

Il faut observer la visibilité des quatre attributs (qui s'appellent publique, protege, defaut, prive) selon leurs positions. Une attribut non visible a été mis en commentaire.

Ce qui se passe à l'intérieur d'un même paquetage

Dans un premier fichier, on a :
package coursJava.monPaquet;

public class EssaiPack
{
  public int publique;
  protected int protege;
  int defaut;
  private int prive;

   protected void ecrire() {}
   protected void dire() {}

}
Dans un second fichier, on peut trouver :
package coursJava.monPaquet;

class Connaissance //meme paquetage que EssaiPack 
{
  EssaiPack essaiPack = new EssaiPack();//instance de EssaiPack 
  int entier;

  Connaissance()
  {
    entier = essaiPack.publique;
    entier = essaiPack.protege;
    entier = essaiPack.defaut;
    //entier = essaiPack.prive;     pas accessible  
    essaiPack.ecrire();	 //  
  }
}

class Etend extends EssaiPack 
	      //classe etendant EssaiPack dans le meme paquetage 
{
  int entier;

  Etend()
  {
    entier = publique;
    entier = protege;
    entier = defaut;
    //entier = prive;          accessible 
    ecrire();	
  }
}
Tous les champs, sauf ceux qui sont privés, sont accessibles de partout dans le paquetage de leur classe.

Ce qui est visible d'un autre paquetage

Pour qu'un quelconque champ d'une classe C d'un paquetage soit visible d'un autre paquetage, il est nécessaire que C soit publique.

Observez ci-dessous. Le cas le plus difficile est celui d'un champ protégé.

package coursJava.autrePaquet;

import coursJava.monPaquet.EssaiPack;

class ConnaissanceAutre
{
  EssaiPack essaiPack = new EssaiPack(); //instance de EssaiPack
  EtendAutre etend = new EtendAutre();
  int entier;

  ConnaissanceAutre()
  {
    entier = essaiPack.publique;
    //entier = essaiPack.protege;   pas accessible
    //entier = essaiPack.defaut;    pas accessible
    //entier = essaiPack.prive;     pas accessible
  
    etend.ecrire();              accesible
    //entier = etend.protege;    pas accessible
    //etend.dire();              pas accesible

   }
}

class EtendAutre extends EssaiPack
	      //classe etendant EssaiPack dans un autre  paquetage 
{
  int entier;

  void faire()
  {
    EssaiPack essaiPack = new EssaiPack();  
    EtendAutre etend = new EtendAutre();
    SousEtend sousEtend = new SousEtend();

    entier = publique;
    entier = protege;
    //entier = defaut;         pas accessible
    //entier = prive;          pas accessible

    entier = essaiPack.publique;
    //entier = essaiPack.protege;   pas accessible
    //entier = essaiPack.defaut;    pas accessible
    //entier = essaiPack.prive;     pas accessible

    entier = etend.protege; 
    entier = sousEtend.protege; 
  } 
  
  protected void ecrire()
    {
      super.ecrire();
    }
}

class SousEtend extends EtendAutre
{
  int entier;

  void faire()
  {
    // entier = (new Etend()).protege;     pas accessible
  }
}
Explicitons le cas des champs protégés ; considérons une classe publique A ; dans un paquetage autre que celui de A, un champ protégé de A n'est accessible que dans une classe héritant de A ; plus précisément, soit B une classe d'un autre paquetage héritant de A ; un champ protégé de A est accessible dans la définition de B : Il n'est accessible dans aucun autre cas.

On constate qu'un champ qui a la visibilité par défaut ou privé n'est pas visible d'un autre paquetage.

Vous pouvez obtenir :

  • Le fichier EssaiPack.java
  • Le fichier qui contient les classes Connaissance et Etend du paquetage coursJavet.monPaquet
  • Le fichier qui contient les trois classes du paquetage coursJava.autrePaquet

    © Irène Charon, Télécom ParisTech 2011