Rappelons qu'une classe permet d'encapsuler à la fois
static ou d'instances sinon) qui définissent l'état d'un objet instanciant cette classe ;static ou d'instance sinon) qui définissent le comportement d'un tel objet.private, protected ou public.
| accès depuis .... sur un membre | private |
pas de spec | protected |
public |
|---|---|---|---|---|
| la classe elle-même | OUI | OUI | OUI | OUI |
| sous-classe même package | NON | OUI | OUI | OUI |
| pas une sous-classe, même package | NON | OUI | OUI | OUI |
| une sous-classe d'un package différent | NON | NON | OUI | OUI |
| pas une sous-classe d'un package différent | NON | NON | NON | OUI |
protected
et private
pour les variables d'instance est crucial en ce qui concerne les
possibilités ultérieures d'y accéder ou non
dans les classes dérivées, même à l'intérieur d'un même
paquetage:
--> cat ProtectedPrivate1.java
class X{
private int x;
protected int y;
X(int x, int y){
this.x = x;
this.y = y;
}
}
class Y extends X{
Y(int x, int y){
super(x, y);
}
}
public class ProtectedPrivate1 {
public static void main(String[] arg){
Y y = new Y(3, 5);
System.out.println(y.x + " " + y.y);
X z = new Y(10, 12);
System.out.println(z.x + " " + z.y);
X x = new Y(1, 2);
System.out.println(x.x + " " + x.y);
}
}
--> javac ProtectedPrivate1.java
ProtectedPrivate1.java:19: x has private access in X
System.out.println(y.x + " " + y.y)
^
ProtectedPrivate1.java:21: x has private access in X
System.out.println(z.x + " " + z.y)
^
ProtectedPrivate1.java:23: x has private access in X
System.out.println(x.x + " " + z.y)
^
3 errors
|
L'accès au champ privé x
de la classe X dont la spécification
est private s'avère
totalement impossible en dehors de la classe. Par contre les méthodes de
la classe peuvent y accéder et il est possible, si besoin est, de fournir
des méthodes permettant aux utilisateurs de la classe de
consulter et/ou modifier une telle variable:
--> cat ProtectedPrivate2.java
class X{
private int x;
protected int y;
X(int x, int y){
this.x = x;
this.y = y;
}
int getX() { return x; }
void setX(int val) {x = val; }
}
class Y extends X{
Y(int x, int y){
super(x, y);
}
void setX(int val) {
System.err.println("modification interdite sur objet de type Y");
}
}
public class ProtectedPrivate2 {
public static void main(String[] arg){
Y y = new Y(3, 5);
System.out.println(y.getX());
y.setX(30);
System.out.println(y.getX());
X z = new Y(10, 12);
System.out.println(z.getX());
z.setX(40);
System.out.println(z.getX());
X x = new X(1, 2);
System.out.println(x.getX());
x.setX(40);
System.out.println(x.getX());
}
}
--> java ProtectedPrivate2
3
modification interdite // objet référencé de la classe Y
3 // pas de modification
10
modification interdite // obj. réf. sur Y par var. de ref. sur X
10 // pas de modification
1
40 // objet de classe X : modification réalisée
|
Cet exemple illustre au passage ce qui est étudié de manière plus
approfondie par ailleurs et touche à la redéfinition et la liaison
tardive.
La méthode setX est redéfinie
dans la classe Y.
Lors de l'exécution, c'est le type de l'objet référencé
et non le type de la variable utilisée pour le référençage qui
détermine la méthode qui est appliquée.