t
t
t
t
t t 5) Cacher l'implémentation
tttt
5) Cacher l'implémentation
Texte original t Traducteur : Phillipe BOITE
t
t
///
Ce chapitre contient 3 pages
1 2 3
\\\
t t t
t t t
t
t t t

Using imports to change behavior

t

Utilisation des imports pour modifier le comportement

t t t
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. t 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.
t t t
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. t 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.
t t t
Here is the class that you’ll use for debugging: t Voici une classe qu'on utilisera pour debugger :
t t t
//: 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);
  }
} ///:~
t
//: 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);
  }
} ///:~
t t t
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. t 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.
t t t
The output is printed to the console standard error stream by writing to System.err. t La sortie est affichée sur la console dans le flux d'erreur standard [standard error stream]en écrivant avec System.err.
t t t
When you want to use this class, you add a line in your program: t Pour utiliser cette classe, ajoutez cette ligne à votre programme :
t t t
import com.bruceeckel.tools.debug.*;
t
import com.bruceeckel.tools.debug.*;
t t t
To remove the assertions so you can ship
the code, a second Assert class is created, but in a different
package:

t Pour supprimer les affirmations afin de pouvoir livrer le code, une deuxième classe Assert est créée, mais dans un package différent :
t t t
//: 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) {}
} ///:~
t
//: 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) {}
} ///:~
t t t
Now if you change the previous import statement to: t Maintenant si on change l'instruction import précédente en :
t t t
import com.bruceeckel.tools.*;
t
import com.bruceeckel.tools.*;
t t t
The program will no longer print
assertions. Here’s an example:

t le programme n'affichera plus d'affirmations. Voici un exemple :
t t t
//: 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");
  }
} ///:~
t
//: 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");
  }
} ///:~
t t t
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. t 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.
t t t

Package caveat

t

Avertissement sur les packages

t t t
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. t 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.
t t t

Java access specifiers

t

Les spécificateurs d'accès Java

t t t
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. t 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é.
t t t
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. t 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.
t t t

“Friendly”

t

« Friendly »

t t t
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. t 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].
t t t
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. t 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.
t t t
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: t 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 :
t t t
  1. Make the member public. Then everybody, everywhere, can access it.
  2. 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.
  3. 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.
  4. 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.
t
  1. Rendre le membre public. Ainsi tout le monde, partout, peut y accéder.
  2. 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.
  3. 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.
  4. 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.
t t t

public: interface access

t

public : accès d'interface

t t t
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: t 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 :
t t t
//: 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"); }
} ///:~
t
//: 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"); }
} ///:~
t t t
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. t 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.
t t t
Now if you create a program that uses Cookie: t Maintenant si on crée un programme qui utilise Cookie :
t t t
//: 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
  }
} ///:~
t
//: 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
  }
} ///:~
t t t
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. t 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.
t t t

The default package

t

Le package par défaut

t t t
You might be surprised to discover that the following code compiles, even though it would appear that it breaks the rules: t Vous pourriez être surpris de découvrir que le code suivant compile, bien qu'il semble ne pas suivre les règles :
t t t
//: 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();
  }
} ///:~
t
//: 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();
  }
} ///:~
t t t
In a second file, in the same directory: t Dans un deuxième fichier, dans le même répertoire :
t t t
//: c05:Pie.java
// The other class.

class Pie {
  void f() { System.out.println("Pie.f()"); }
} ///:~
t
//: c05:Pie.java
// L'autre classe.
class Pie {
  void f() { System.out.println("Pie.f()"); }
} ///:~
t t t
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. t 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.
t t t

private: you can’t touch that!

t

private : ne pas toucher !

t t t
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. t 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.
t t t
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.) t 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).
t t t
Here’s an example of the use of private: t Voici un exemple de l'utilisation de private :
t t t
//: 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();
  }
} ///:~
t
//: 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();
  }
} ///:~
t t t
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]. t 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].
t t t
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. t 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.
t t t
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.) t 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).
t t t

protected: “sort of friendly”

t

protected : « sorte d'amical »

t t t
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. t 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.
t t t
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: t 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 :
t t t
class Foo extends Bar {
t
class Foo extends Bar {
t t t
The rest of the class definition looks
the same.
t Le reste de la définition de la classe est inchangé.
t t t
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:

t 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 » :
t t t
//: 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
  }
} ///:~
t
//: 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
  }
} ///:~
t t t
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: t 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 :
t t t
public class Cookie {
  public Cookie() {
    System.out.println("Cookie constructor");
  }
  protected void bite() {
    System.out.println("bite");
  }
}
t
public class Cookie {
  public Cookie() {
    System.out.println("Cookie constructor");
  }
  protected void bite() {
    System.out.println("bite");
  }
}
t t t
then bite( ) still has “friendly” access within package dessert, but it is also accessible to anyone inheriting from Cookie. However, it is not public. t 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.
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel