 |
 |
5) Cacher l'implémentation |
|
 |
|
Texte original |
 |
Traducteur : Phillipe BOITE |
|
 |
///
|
Ce chapitre contient 3 pages
1
2
3
|
|
|
 |
 |
 |
 |
 |
 |
|
 |
|
 |
 |
 |
Using imports to change behavior
|
 |
Utilisation des imports pour modifier le comportement
|
 |
 |
 |
A feature that is missing from Java is
C’s conditional compilation, which allows you to change a switch
and get different behavior without changing any other code. The reason such a
feature was left out of Java is probably because it is most often used in C to
solve cross-platform issues: different portions of the code are compiled
depending on the platform that the code is being compiled for. Since Java is
intended to be automatically cross-platform, such a feature should not be
necessary.
|
 |
Une caractéristique manquant à Java est la compilation
conditionelle du C, qui permet de changer un commutateur pour obtenir un comportement
différent sans rien changer d'autre au code. La raison pour laquelle cette caractéristique n'a pas
été retenue en Java est probablement qu'elle est surtout utilisée en C pour résoudre des problèmes
de portabilité : des parties du code sont compilées différemment selon la plateforme pour laquelle
le code est compilé. Comme le but de Java est d'être automatiquement portable, une telle
caractéristique ne devrait pas être nécessaire.
|
 |
 |
 |
However, there are other valuable uses
for conditional compilation. A very common use is for debugging code. The
debugging features are enabled during development, and disabled in the shipping
product. Allen Holub (www.holub.com) came up with the idea of using
packages to mimic conditional compilation. He used this to create a Java version
of C’s very useful assertion mechanism, whereby you can say
“this should be true” or “this should be false” and if
the statement doesn’t agree with your assertion you’ll find out
about it. Such a tool is quite helpful during debugging.
|
 |
Il y a cependant d'autres utilisations valables de la compilation
conditionnelle. Un usage très courant est le debug de code. Les possibilités de debug sont validées
pendant le développement, et invalidées dans le produit livré. Allen Holub (www.holub.com)
a eu l'idée d'utiliser les packages pour imiter la compilation conditionnelle. Il l'a utilisée pour
créer une version du très utile mécanisme d'affirmation [assertion
mechanism] du C, dans lequel on peut dire « ceci devrait être vrai » ou « ceci devrait être faux »
et si l'instruction n'est pas d'accord avec cette affirmation, on en sera averti. Un tel outil est
très utile pendant la phase de debuggage.
|
 |
 |
 |
Here is the class that you’ll use
for debugging:
|
 |
Voici une classe qu'on utilisera pour debugger :
|
 |
 |
 |
//: com:bruceeckel:tools:debug:Assert.java // Assertion tool for debugging. package com.bruceeckel.tools.debug;
public class Assert { private static void perr(String msg) { System.err.println(msg); } public final static void is_true(boolean exp) { if(!exp) perr("Assertion failed"); } public final static void is_false(boolean exp){ if(exp) perr("Assertion failed"); } public final static void is_true(boolean exp, String msg) { if(!exp) perr("Assertion failed: " + msg); } public final static void is_false(boolean exp, String msg) { if(exp) perr("Assertion failed: " + msg); } } ///:~
|
 |
//: com:bruceeckel:tools:debug:Assert.java // Outil d'affirmation pour debugger package com.bruceeckel.tools.debug; public class Assert { private static void perr(String msg) { System.err.println(msg); } public final static void is_true(boolean exp) { if(!exp) perr("Assertion failed"); } public final static void is_false(boolean exp){ if(exp) perr("Assertion failed"); } public final static void is_true(boolean exp, String msg) { if(!exp) perr("Assertion failed: " + msg); } public final static void is_false(boolean exp, String msg) { if(exp) perr("Assertion failed: " + msg); } } ///:~
|
 |
 |
 |
This class simply encapsulates Boolean
tests, which print error messages if they fail. In Chapter 10, you’ll
learn about a more sophisticated tool for dealing with errors called
exception handling, but the perr( ) method will work fine in
the meantime.
|
 |
Cette classe encapsule simplement des tests booléens, qui impriment des
messages d'erreur en cas d'échec. Dans le chapitre 10, on apprendra à utiliser un outil plus
sophistiqué pour traiter les erreurs, appelé traitement d'exceptions
[exception handling], mais la méthode perr( ) conviendra
bien en attendant.
|
 |
 |
 |
The output is printed to the console
standard error stream by writing to System.err.
|
 |
La sortie est affichée sur la console dans le flux d'erreur
standard [standard error stream]en écrivant avec
System.err.
|
 |
 |
 |
When you want to use this class, you add
a line in your program:
|
 |
Pour utiliser cette classe, ajoutez cette ligne à votre programme
:
|
 |
 |
 |
import com.bruceeckel.tools.debug.*;
|
 |
import com.bruceeckel.tools.debug.*;
|
 |
 |
 |
To remove the assertions so you can ship the code, a second Assert class is created, but in a different package:
|
 |
Pour supprimer les affirmations afin de pouvoir livrer le code, une
deuxième classe Assert est créée, mais dans un package différent :
|
 |
 |
 |
//: com:bruceeckel:tools:Assert.java // Turning off the assertion output // so you can ship the program. package com.bruceeckel.tools;
public class Assert { public final static void is_true(boolean exp){} public final static void is_false(boolean exp){} public final static void is_true(boolean exp, String msg) {} public final static void is_false(boolean exp, String msg) {} } ///:~
|
 |
//: com:bruceeckel:tools:Assert.java // Suppression de la sortie de l'affirmation // pour pouvoir livrer le programme. package com.bruceeckel.tools; public class Assert { public final static void is_true(boolean exp){} public final static void is_false(boolean exp){} public final static void is_true(boolean exp, String msg) {} public final static void is_false(boolean exp, String msg) {} } ///:~
|
 |
 |
 |
Now if you change the previous
import statement to:
|
 |
Maintenant si on change l'instruction import précédente en
:
|
 |
 |
 |
import com.bruceeckel.tools.*;
|
 |
import com.bruceeckel.tools.*;
|
 |
 |
 |
The program will no longer print assertions. Here’s an example:
|
 |
le programme n'affichera plus d'affirmations. Voici un exemple :
|
 |
 |
 |
//: c05:TestAssert.java // Demonstrating the assertion tool. // Comment the following, and uncomment the // subsequent line to change assertion behavior: import com.bruceeckel.tools.debug.*; // import com.bruceeckel.tools.*;
public class TestAssert { public static void main(String[] args) { Assert.is_true((2 + 2) == 5); Assert.is_false((1 + 1) == 2); Assert.is_true((2 + 2) == 5, "2 + 2 == 5"); Assert.is_false((1 + 1) == 2, "1 +1 != 2"); } } ///:~
|
 |
//: c05:TestAssert.java // Démonstration de l'outil d'affirmation. // Mettre en commentaires ce qui suit, et enlever // le commentaire de la ligne suivante // pour modifier le comportement de l'affirmation : import com.bruceeckel.tools.debug.*; // import com.bruceeckel.tools.*; public class TestAssert { public static void main(String[] args) { Assert.is_true((2 + 2) == 5); Assert.is_false((1 + 1) == 2); Assert.is_true((2 + 2) == 5, "2 + 2 == 5"); Assert.is_false((1 + 1) == 2, "1 +1 != 2"); } } ///:~
|
 |
 |
 |
By changing the package
that’s imported, you change your code from the debug version to the
production version. This technique can be used for any kind of conditional
code.
|
 |
En changeant le package qui est importé, on change le code de la version
debug à la version de production. Cette technique peut être utilisée pour toutes sortes de code
conditionnel.
|
 |
 |
 |
Package caveat
|
 |
Avertissement sur les packages
|
 |
 |
 |
It’s worth remembering that anytime
you create a package, you implicitly specify a
directory structure when you give
the package a name. The package must live in the directory indicated by
its name, which must be a directory that is searchable starting from the
CLASSPATH. Experimenting with the package keyword can be a bit
frustrating at first, because unless you adhere to the package-name to
directory-path rule, you’ll get a lot of mysterious run-time messages
about not being able to find a particular class, even if that class is sitting
there in the same directory. If you get a message like this, try commenting out
the package statement, and if it runs you’ll know where the problem
lies.
|
 |
Il faut se rappeler que chaque fois qu'on crée un package, on spécifie
implicitement une structure de répertoire en donnant un nom à un package. Le package doit
se trouver dans le répertoire indiqué par son nom, qui doit être un répertoire qui peut être trouvé
en partant du CLASSPATH. L'utilisation du mot-clé package peut être un peu
frustrante au début, car à moins d'adhérer à la règle nom-de-package - chemin-de-répertoire, on
obtient un tas de messages mystérieux à l'exécution signalant l'impossibilité de trouver une classe
donnée, même si la classe est là dans le même répertoire. Si vous obtenez un message de ce type,
essayez de mettre en commentaire l'instruction package, et si ça tourne vous
saurez où se trouve le problème.
|
 |
 |
 |
Java access specifiers
|
 |
Les spécificateurs d'accès Java
|
 |
 |
 |
When used, the Java
access specifiers
public, protected,
and private are placed in front of each definition
for each member in your class, whether it’s a field or a method. Each
access specifier controls the access for only that particular definition. This
is a distinct contrast to C++, in which the access specifier controls all the
definitions following it until another access specifier comes
along.
|
 |
Quand on les utilise, les spécificateurs d'accès Java public,
protected, et private sont placés devant la définition de chaque
membre de votre classe, qu'il s'agisse d'un champ ou d'une méthode. Chaque spécificateur d'accès
contrôle l'accès pour uniquement cette définition particulière. Ceci est différent du C++, où un
spécificateur d'accès contrôle toutes les définitions le suivant jusqu'à ce qu'un autre
spécificateur d'accès soit rencontré.
|
 |
 |
 |
One way or another, everything has some
kind of access specified for it. In the following sections, you’ll learn
all about the various types of access, starting with the default
access.
|
 |
D'une façon ou d'une autre, toute chose a un type d'accès spécifié. Dans
les sections suivantes, vous apprendrez à utiliser les différents types d'accès, à commencer par
l'accès par défaut.
|
 |
 |
 |
“Friendly”
|
 |
« Friendly »
|
 |
 |
 |
What if you give no access specifier at
all, as in all the examples before this chapter? The default access has no
keyword, but it is commonly referred to as “friendly.” It means that
all the other classes in the current package have access to the friendly member,
but to all the classes outside of this package the member appears to be
private. Since a compilation unit—a file—can belong only to a
single package, all the classes within a single compilation unit are
automatically friendly with each other. Thus, friendly elements are also said to
have package
access.
|
 |
Que se passe-t-il si on ne précise aucun spécificateur d'accès, comme dans
tous les exemples avant ce chapitre ? L'accès par défaut n'a pas de mot-clé, mais on l'appelle
couramment « friendly » (amical). Cela veut dire que toutes les autres classes du package courant ont
accès au membre amical, mais pour toutes les classes hors du package le membre apparaît
private. Comme une unité de compilation -un fichier- ne peut appartenir qu'à un
seul package, toutes les classes d'une unité de compilation sont automatiquement amicales entre
elles. De ce fait, on dit aussi que les éléments amicaux ont un accès de
package[package access].
|
 |
 |
 |
Friendly access allows you to group
related classes together in a package so that they can easily interact with each
other. When you put classes together in a package (thus granting mutual access
to their friendly members; e.g., making them “friends”) you
“own” the code in that package. It makes sense that only code you
own should have friendly access to other code you own. You could say that
friendly access gives a meaning or a reason for grouping classes together in a
package. In many languages the way you organize your definitions in files can be
willy-nilly, but in Java you’re compelled to
organize them in a sensible
fashion. In addition, you’ll probably want to exclude classes that
shouldn’t have access to the classes being defined in the current
package.
|
 |
L'accès amical permet de grouper des classes ayant des points communs dans
un package, afin qu'elles puissent facilement interagir entre elles. Quand on met des classes
ensemble dans un package (leur accordant de ce fait un accès mutuel à leurs membres amicaux, c'est
à dire en les rendant « amicaux » ) on « possède » le code de ce package. Il est logique que seul le
code qu'on possède ait un accès amical à un autre code qu'on possède. On pourrait dire que l'accès
amical donne une signification ou une raison pour regrouper des classes dans un package. Dans
beaucoup de langages l'organisation des définitions dans des fichiers peut être faite tant bien que
mal, mais en Java on est astreint à les organiser d'une manière logique. De plus, on exclura
probablement les classes qui ne devraient pas avoir accès aux classes définies dans le package
courant.
|
 |
 |
 |
The class controls which code has access
to its members. There’s no magic way to “break in.” Code from
another package can’t show up and say, “Hi, I’m a friend of
Bob’s!” and expect to see the protected, friendly, and
private members of Bob. The only way to grant access to a member
is to:
|
 |
La classe contrôle quel code a accès à ses membres. Il n'y a pas de moyen
magique pour « entrer par effraction ». Le code d'un autre package ne peut pas dire « Bonjour, je suis
un ami de Bob ! » et voir les membres protected, friendly, et
private de Bob. La seule façon d'accorder l'accès à un membre est
de :
|
 |
 |
 |
- Make the member
public. Then everybody, everywhere, can access
it.
- Make the member
friendly by leaving off any access specifier, and put the other classes in the
same package. Then the other classes can access the
member.
- As
you’ll see in Chapter 6, when inheritance is introduced, an inherited
class can access a protected member as well as a public member
(but not private members). It can access friendly members only if the two
classes are in the same package. But don’t worry about that
now.
- Provide
“accessor/mutator” methods (also known as “get/set”
methods) that read and change the value. This is the most civilized approach in
terms of OOP, and it is fundamental to JavaBeans, as you’ll see in Chapter
13.
|
 |
- Rendre le membre public. Ainsi tout le monde, partout,
peut y accéder.
- Rendre le membre amical en n'utilisant aucun spécificateur d'accès, et
mettre les autres classes dans le même package. Ainsi les autres classes peuvent accéder à ce
membre.
- Comme on le verra au Chapitre 6, lorsque l'héritage sera présenté, une
classe héritée peut avoir accès à un membre protected ou public
(mais pas à des membres private). Elle peut accéder à des membres amicaux
seulement si les deux classes sont dans le même package. Mais vous n'avez pas besoin de vous
occuper de cela maintenant.
- Fournir des méthodes « accessor/mutator » (connues aussi sous le nom de
méthodes « get/set » ) qui lisent et changent la valeur. Ceci est l'approche la plus civilisée en
termes de programmation orientée objet, et elle est fondamentale pour les JavaBeans, comme on le
verra dans le Chapitre 13.
|
 |
 |
 |
public: interface access
|
 |
public : accès d'interface
|
 |
 |
 |
When you use the public keyword,
it means that the member declaration that immediately
follows public is available to everyone, in particular to the client
programmer who uses the library. Suppose you define a package dessert
containing the following compilation unit:
|
 |
Lorsqu'on utilise le mot-clé public, cela signifie que la
déclaration du membre qui suit immédiatement public est disponible pour tout le
monde, en particulier pour le programmeur client qui utilise la bibliothèque. Supposons qu'on
définisse un package dessert contenant l'unité de compilation suivante
:
|
 |
 |
 |
//: c05:dessert:Cookie.java // Creates a library. package c05.dessert;
public class Cookie { public Cookie() { System.out.println("Cookie constructor"); } void bite() { System.out.println("bite"); } } ///:~
|
 |
//: c05:dessert:Cookie.java // Création d'une bibliothèque. package c05.dessert; public class Cookie { public Cookie() { System.out.println("Cookie constructor"); } void bite() { System.out.println("bite"); } } ///:~
|
 |
 |
 |
Remember, Cookie.java must reside
in a subdirectory called dessert, in a directory under c05
(indicating Chapter 5 of this book) that must be under one of the CLASSPATH
directories. Don’t make the mistake of thinking that Java will always look
at the current directory as one of the starting points for searching. If you
don’t have a ‘.’ as one of the paths in your CLASSPATH,
Java won’t look there.
|
 |
Souvenez-vous, Cookie.java doit se trouver dans un
sous-répertoire appelé dessert, en dessous de c05 (qui signifie
le Chapitre 5 de ce livre) qui doit être en-dessous d'un des répertoire du CLASSPATH. Ne faites pas
l'erreur de croire que Java va toujours considérer le répertoire courant comme l'un des points de
départ de la recherche. Si vous n'avez pas un « . » comme un des chemins dans votre
CLASSPATH, Java n'y regardera pas.
|
 |
 |
 |
Now if you create a program that uses
Cookie:
|
 |
Maintenant si on crée un programme qui utilise Cookie
:
|
 |
 |
 |
//: c05:Dinner.java // Uses the library. import c05.dessert.*;
public class Dinner { public Dinner() { System.out.println("Dinner constructor"); } public static void main(String[] args) { Cookie x = new Cookie(); //! x.bite(); // Can't access } } ///:~
|
 |
//: c05:Dinner.java // Utilise la bibliothèque. import c05.dessert.*;
public class Dinner { public Dinner() { System.out.println("Dinner constructor"); } public static void main(String[] args) { Cookie x = new Cookie(); //! x.bite(); // Ne peut y accéder } } ///:~
|
 |
 |
 |
you can create a Cookie object,
since its constructor is public and the class is public.
(We’ll look more at the concept of a public class later.) However,
the bite( ) member is inaccessible inside Dinner.java since
bite( ) is friendly only within package
dessert.
|
 |
on peut créer un objet Cookie, puisque son constructeur
est public et que la classe est public. (Nous allons regarder
plus en détail le concept d'une classe public plus tard.) Cependant, le membre
bite() est inaccessible depuis Dinner.java car
bite() est amical uniquement à l'intérieur du package
dessert.
|
 |
 |
 |
The default
package
|
 |
Le package par défaut
|
 |
 |
 |
You might be surprised to discover that
the following code compiles, even though it would appear that it breaks the
rules:
|
 |
Vous pourriez être surpris de découvrir que le code suivant compile, bien
qu'il semble ne pas suivre les règles :
|
 |
 |
 |
//: c05:Cake.java // Accesses a class in a // separate compilation unit.
class Cake { public static void main(String[] args) { Pie x = new Pie(); x.f(); } } ///:~
|
 |
//: c05:Cake.java // Accède à une classe dans // une unité de compilation séparée. class Cake { public static void main(String[] args) { Pie x = new Pie(); x.f(); } } ///:~
|
 |
 |
 |
In a second file, in the same
directory:
|
 |
Dans un deuxième fichier, dans le même répertoire :
|
 |
 |
 |
//: c05:Pie.java // The other class.
class Pie { void f() { System.out.println("Pie.f()"); } } ///:~
|
 |
//: c05:Pie.java // L'autre classe. class Pie { void f() { System.out.println("Pie.f()"); } } ///:~
|
 |
 |
 |
You might initially view these as
completely foreign files, and yet Cake is able to create a Pie
object and call its f( ) method! (Note that you must have
‘.’ in your CLASSPATH in order for the files to compile.)
You’d typically think that Pie and f( ) are friendly
and therefore not available to Cake. They are friendly—that
part is correct. The reason that they are available in Cake.java is
because they are in the same directory and have no explicit package name. Java
treats files like this as implicitly part of the “default package”
for that directory, and therefore friendly to all the other files in that
directory.
|
 |
On pourrait à première vue considére ces fichiers comme complètement
étrangers l'un à l'autre, et cependant Cake est capable de créer l'objet
Pie et d'appeler sa méthode f() ! (Remarquez qu'il faut avoir « . »
dans le CLASSPATH pour que ces fichiers puissent être compilés.) On penserait normalement que
Pie et f() sont amicaux et donc non accessibles par
Cake. Ils sont amicaux, cette partie-là est exacte. La raison pour
laquelle ils sont accessible dans Cake.java est qu'ils sont dans le même
répertoire et qu'ils n'ont pas de nom de package explicite. Java traite de tels fichiers comme
faisant partie du « package par défaut » pour ce répertoire, et donc amical pour tous les autres
fichiers du répertoire.
|
 |
 |
 |
private: you can’t touch that!
|
 |
private : ne pas toucher !
|
 |
 |
 |
The private
keyword means that no one can access that member except
that particular class, inside methods of that class. Other classes in the same
package cannot access private members, so it’s as if you’re
even insulating the class against yourself. On the other hand, it’s not
unlikely that a package might be created by several people collaborating
together, so private allows you to freely change that member without
concern that it will affect another class in the same package.
|
 |
Le mot-clé private signifie que personne ne peut
accéder à ce membre à part la classe en question, dans les méthodes de cette classe. Les autres
classes du package ne peuvent accéder à des membres private, et c'est donc un peu
comme si on protégeait la classe contre soi-même. D'un autre côté il n'est pas impossible qu'un
package soit codé par plusieurs personnes, et dans ce cas private permet de
modifier librement ce membre sans que cela affecte une autre classe dans le même package.
|
 |
 |
 |
The default “friendly”
package access often provides an adequate amount of hiding; remember, a
“friendly” member is inaccessible to the user of the package. This
is nice, since the default access is the one that you normally use (and the one
that you’ll get if you forget to add any access control). Thus,
you’ll typically think about access for the members that you explicitly
want to make public for the client programmer, and as a result, you might
not initially think you’ll use the private keyword often
since it’s tolerable to get away without it. (This is a distinct contrast
with C++.) However, it turns out that the consistent use of private is
very important, especially where multithreading is concerned. (As you’ll
see in Chapter 14.)
|
 |
L'accès « amical » par défaut dans un package cache souvent suffisamment les
choses ; souvenez-vous, un membre « amical » est inaccessible à l'utilisateur du package. C'est
parfait puisque l'accès par défaut est celui qu'on utilise normalement (et c'est celui qu'on
obtient si on oublie d'ajouter un contrôle d'accès). De ce fait, on ne pensera normalement qu'aux
accès aux membres qu'on veut explicitement rendre public pour le programmeur
client, et donc on pourrait penser qu'on n'utilise pas souvent le mot-clé private
puisqu'on peut s'en passer (ceci est une différence par rapport au C++). Cependant, il se fait que
l'utilisation cohérente de private est très importante, particulièrement lors du
multithreading (comme on le verra au Chapitre 14).
|
 |
 |
 |
Here’s an example of the use of
private:
|
 |
Voici un exemple de l'utilisation de private :
|
 |
 |
 |
//: c05:IceCream.java // Demonstrates "private" keyword.
class Sundae { private Sundae() {} static Sundae makeASundae() { return new Sundae(); } }
public class IceCream { public static void main(String[] args) { //! Sundae x = new Sundae(); Sundae x = Sundae.makeASundae(); } } ///:~
|
 |
//: c05:IceCream.java // Démontre le mot-clé "private" class Sundae { private Sundae() {} static Sundae makeASundae() { return new Sundae(); } }
public class IceCream { public static void main(String[] args) { //! Sundae x = new Sundae(); Sundae x = Sundae.makeASundae(); } } ///:~
|
 |
 |
 |
This shows an example in which
private comes in handy: you might want to control how an object is
created and prevent someone from directly accessing a particular constructor (or
all of them). In the example above, you cannot create a Sundae object via
its constructor; instead you must call the makeASundae( ) method to
do it for
you[33].
|
 |
Ceci montre un cas où private vient à propos : on peut
vouloir contrôler comment un objet est créé et empêcher quelqu'un d'accéder à un constructeur en
particulier (ou à tous). Dans l'exemple ci-dessus, on ne peut pas créer un objet
Sundae à l'aide de son constructeur ; il faut plutôt utiliser la méthode
makeASundae() qui le fera pour nous [33].
|
 |
 |
 |
Any method that you’re certain is
only a “helper” method for that class can be made private, to
ensure that you don’t accidentally use it elsewhere in the package and
thus prohibit yourself from changing or removing the method. Making a method
private guarantees that you retain this option.
|
 |
Toute méthode dont on est certain qu'elle n'est utile qu'à cette classe
peut être rendue private, pour s'assurer qu'on ne l'utilisera pas ailleurs dans le
package, nous interdisant ainsi de la modifier ou de la supprimer. Rendre une méthode
private garantit cela.
|
 |
 |
 |
The same is true for a private
field inside a class. Unless you must expose the underlying implementation
(which is a much rarer situation than you might think), you should make all
fields private. However, just because a reference to an object is
private inside a class doesn't mean that some other object can't have a
public reference to the same object. (See Appendix A for issues about
aliasing.)
|
 |
Ceci est également vrai pour un champ private dans une
classe. A moins qu'on ne doive exposer une implémentation sous-jacente (ce qui est beaucoup plus
rare qu'on ne pourrait penser), on devrait déclarer tous les membres private. Cependant, le fait
que la référence à un objet est private dans une classe ne signifie pas qu'un
autre objet ne puisse avoir une référence public à cet objet (voir l'annexe A pour
les problèmes au sujet de l'aliasing).
|
 |
 |
 |
protected: “sort of friendly”
|
 |
protected : « sorte d'amical »
|
 |
 |
 |
The protected access specifier
requires a jump ahead to understand. First, you should be
aware that you don’t need to understand this section to continue through
this book up through inheritance (Chapter 6). But for completeness, here is a
brief description and example using protected.
|
 |
Le spécificateur d'accès protected demande un effort de
compréhension . Tout d'abord, il faut savoir que vous n'avez pas besoin de comprendre cette partie
pour continuer ce livre jusqu'à l'héritage (Chapitre 6). Mais pour être complet, voici une brève
description et un exemple d'utilisation de protected.
|
 |
 |
 |
The protected keyword deals with a
concept called inheritance, which takes an
existing class and adds new members to that class without touching the existing
class, which we refer to as the
base class. You can
also change the behavior of existing members of the class. To inherit from an
existing class, you say that your new class extends
an existing class, like this:
|
 |
Le mot-clé protected traite un concept appelé
héritage, qui prend une classe existante et ajoute des membres à cette classe sans
modifier la classe existante, que nous appellerons la classe de base. On peut également
changer le comportement des membres d'une classe existants. Pour hériter d'une classe existante, on
dit que le nouvelle classe extends (étend) une classe existante, comme ceci
:
|
 |
 |
 |
class Foo extends Bar {
|
 |
class Foo extends Bar {
|
 |
 |
 |
The rest of the class definition looks the same.
|
 |
Le reste de la définition de la classe est inchangé.
|
 |
 |
 |
If you create a new package and you inherit from a class in another package, the only members you have access to are the public members of the original package. (Of course, if you perform the inheritance in the same package, you have the normal package access to all the “friendly” members.) Sometimes the creator of the base class would like to take a particular member and grant access to derived classes but not the world in general. That’s what protected does. If you refer back to the file Cookie.java, the following class cannot access the “friendly” member:
|
 |
Si on crée un nouveau package et qu'on hérite d'une classe d'un autre
package, les seuls membres accessibles sont les membres public du package
d'origine. (Bien sûr, si on effectue l'héritage dans le même package, on a l'accès normal
à tous les membres « amicaux » du package.) Parfois le créateur de la classe de base veut, pour un
membre particulier, en accorder l'accès dans les classes dérivées mais pas dans le monde entier en
général. C'est ce que protected fait. Si on reprend le fichier
Cookie.java, la classe suivante ne peut pas accéder au membre « amical »
:
|
 |
 |
 |
//: c05:ChocolateChip.java // Can't access friendly member // in another class. import c05.dessert.*;
public class ChocolateChip extends Cookie { public ChocolateChip() { System.out.println( "ChocolateChip constructor"); } public static void main(String[] args) { ChocolateChip x = new ChocolateChip(); //! x.bite(); // Can't access bite } } ///:~
|
 |
//: c05:ChocolateChip.java // Nepeut pas accéder à un membre amical // dans une autre classe. import c05.dessert.*;
public class ChocolateChip extends Cookie { public ChocolateChip() { System.out.println( "ChocolateChip constructor"); } public static void main(String[] args) { ChocolateChip x = new ChocolateChip(); //! x.bite(); // Ne peut pas accéder à bite } } ///:~
|
 |
 |
 |
One of the interesting things about
inheritance is that if a method bite( ) exists in class
Cookie, then it also exists in any class inherited from Cookie.
But since bite( ) is “friendly” in a foreign package,
it’s unavailable to us in this one. Of course, you could make it
public, but then everyone would have access and maybe that’s not
what you want. If we change the class Cookie as follows:
|
 |
Une des particularités intéressantes de l'héritage est que si la méthode
bite() existe dans la classe Cookie, alors elle existe aussi dans toute classe
héritée de Cookie. Mais comme bite() est « amical » dans un autre package, il nous
est inaccessible dans celui-ci. Bien sûr, on pourrait le rendre public, mais alors
tout le monde y aurait accès, ce qui ne serait peut-être pas ce qu'on veut. Si on modifie la classe
Cookie comme ceci :
|
 |
 |
 |
public class Cookie { public Cookie() { System.out.println("Cookie constructor"); } protected void bite() { System.out.println("bite"); } }
|
 |
public class Cookie { public Cookie() { System.out.println("Cookie constructor"); } protected void bite() { System.out.println("bite"); } }
|
 |
 |
 |
then bite( ) still has
“friendly” access within package dessert, but it is also
accessible to anyone inheriting from Cookie. However, it is not
public.
|
 |
alors bite() est toujours d'accès « amical » dans le package
dessert, mais il est aussi accessible à tous ceux qui héritent de
Cookie. Cependant, il n'est pas public.
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |