JavaRush /Blog Java /Random-FR /Modificateurs d'accès. Privé, protégé, par défaut, public...

Modificateurs d'accès. Privé, protégé, par défaut, public

Publié dans le groupe Random-FR
Bonjour! Dans la conférence d'aujourd'hui, nous nous familiariserons avec le concept de « modificateurs d'accès » et examinerons des exemples de travail avec eux. Modificateurs d'accès.  Privé, protégé, par défaut, public - 1Bien que le mot « faisons connaissance » ne soit pas tout à fait correct : vous connaissez déjà la plupart d'entre eux grâce aux conférences précédentes. Au cas où, rafraîchissons-nous la mémoire sur l'essentiel. Les modificateurs d'accès sont le plus souvent des mots-clés qui régulent le niveau d'accès aux différentes parties de votre code. Pourquoi « le plus souvent » ? Parce que l'un d'eux est défini par défaut et n'est pas indiqué par un mot-clé :) Il existe un total de quatre modificateurs d'accès en Java. Nous les listons du plus strict au plus « soft » :
  • privé;
  • protégé;
  • par défaut (paquet visible) ;
  • publique.
Examinons chacun d'eux, décidons quand ils peuvent nous être utiles et donnons des exemples :)

Modificateur privé

Modificateurs d'accès.  Privé, protégé, par défaut, public - 2Private— le modificateur d'accès le plus restrictif. Cela limite la visibilité des données et des méthodes au sein d’une seule classe. Vous connaissez ce modificateur grâce à la conférence sur les getters et les setters. Vous souvenez-vous de cet exemple ?
public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Nous l'avons examiné dans l'un des articles précédents. Ici, nous avons commis une grave erreur : nous avons ouvert nos données, ce qui a permis à d'autres programmeurs d'accéder directement aux champs de classe et de modifier leurs valeurs. De plus, ces valeurs ont été attribuées sans contrôle, ce qui permet dans notre programme de créer un chat avec un âge de -1000 ans, un nom "" et un poids de 0. Pour résoudre ce problème, nous utilisé des getters et des setters , et également limité l'accès aux données à l'aide d'un modificateur private.
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // checking the input parameter
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // checking the input parameter
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // checking the input parameter
       this.weight = weight;
   }
}
En fait, restreindre l'accès aux champs et implémenter des getters-setters est l'exemple d'utilisation le plus courant privatedans le travail réel. Autrement dit, l'implémentation de l'encapsulation dans un programme est l'objectif principal de ce modificateur. Cela ne s'applique d'ailleurs pas seulement aux champs. Imaginez que dans votre programme il existe une méthode qui implémente des fonctionnalités TRÈS complexes. Pour donner ceci comme exemple... Disons que votre méthode readDataFromCollider()prend une adresse avec des données en entrée, lit les données du Grand collisionneur de hadrons au format octet, convertit ces données en texte, les écrit dans un fichier et les imprime. Même la description de la méthode semble effrayante, sans parler du code :) Pour augmenter la lisibilité du code, il serait bien de ne pas écrire la logique complexe de la méthode au même endroit, mais, au contraire, de casser la fonctionnalité en méthodes distinctes. Par exemple, la méthode readByteData()est chargée de lire les données, convertBytesToSymbols()de convertir les données lues à partir du collisionneur en texte, saveToFile()d'enregistrer le texte résultant dans un fichier et printColliderData()d'imprimer notre fichier de données. La méthode readDataFromCollider()serait finalement beaucoup plus simple :
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // convert bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // save the read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // print data from file
   }
}
Cependant, comme vous vous en souvenez lors du cours sur les interfaces, l'utilisateur n'a accès qu'à l'interface finale. Et nos 4 méthodes n’en font pas partie. Ils sont auxiliaires : nous les avons créés pour améliorer la lisibilité du code et éviter de regrouper quatre tâches différentes dans une seule méthode. Il n'est pas nécessaire de donner à l'utilisateur l'accès à ces méthodes. Si un utilisateur a accès à la méthode lorsqu'il travaille avec un collisionneur convertBytesToSymbols(), il ne comprendra probablement tout simplement pas ce qu'est cette méthode et pourquoi elle est nécessaire. Quels octets sont convertis ? D'où viennent-ils? Pourquoi les convertir en texte ? La logique exécutée dans cette méthode ne fait pas partie de l'interface utilisateur. Seule la méthode readDataFromCollider()fait partie de l'interface. Que faire de ces quatre méthodes « internes » ? Droite! Restreindre leur accès avec un modificateur private. De cette façon, ils peuvent facilement faire leur travail à l'intérieur de la classe et ne pas dérouter l'utilisateur, qui n'a pas besoin de la logique de chacun d'eux séparément.
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // convert bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // save the read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // print data from file
   }
}

Modificateur protégé

Le prochain modificateur d’accès le plus restrictif est protected. Modificateurs d'accès.  Privé, protégé, par défaut, public - 3 Les champs et méthodes désignés avec le modificateur d'accès protectedseront visibles :
  • dans toutes les classes qui sont dans le même package que le nôtre ;
  • au sein de toutes les classes successeurs de notre classe.
Il est immédiatement difficile d’imaginer quand cela pourrait être nécessaire. Ne soyez pas surpris : protectedles cas d’application sont bien moins nombreux que private, et ils sont spécifiques. Imaginez que nous ayons une classe abstraite AbstractSecretAgentqui désigne un agent secret d'un service spécial, ainsi qu'un package top_secretcontenant cette classe et ses descendants. Des classes concrètes - FBISecretAgent, MI6SecretAgent, MossadSecretAgentetc. - en sont héritées. Dans la classe abstraite, nous souhaitons implémenter un compteur d'agent. Lorsqu'un nouvel objet agent est créé quelque part dans le programme, il augmentera.
package top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Mais nos agents sont secrets ! Cela signifie que seuls eux et personne d’autre devraient connaître leur numéro. Nous pouvons facilement ajouter un modificateur protectedau champ agentCount, et alors soit les objets d'autres classes d'agents secrets, soit les classes qui se trouvent dans notre package « secret », peuvent obtenir sa valeur top_secret.
public abstract class AbstractSecretAgent {

   protected static int agentCount = 0;
}
C'est pour des tâches aussi spécifiques qu'un modificateur est nécessaire protected:)

modificateur visible du package

Le prochain sur notre liste est le modificateur defaultou, comme on l'appelle aussi, package visible. Il n'est pas indiqué par un mot-clé car il est défini par défaut en Java pour tous les champs et méthodes. Si vous écrivez dans votre code -
int x = 10;
... la variable xaura ce même package visibleaccès. Si une méthode (ou une variable) n'est marquée d'aucun modificateur, elle est considérée comme marquée du "modificateur par défaut". Les variables ou méthodes avec un tel modificateur (c'est-à-dire sans aucun) sont visibles par toutes les classes du package dans lequel elles sont déclarées. Et seulement à eux. Ses utilisations sont limitées, tout comme le modificateur protected. Le plus souvent, default-access est utilisé dans un package dans lequel certaines classes utilitaires n'implémentent pas les fonctionnalités de toutes les autres classes de ce package. Donnons un exemple. Imaginez que nous ayons un package « services ». À l'intérieur se trouvent diverses classes qui fonctionnent avec la base de données. Par exemple, il existe une classe UserServicequi lit les données utilisateur d'une base de données, une classe CarServicequi lit les données sur les voitures de la même base de données et d'autres classes, chacune travaillant avec son propre type d'objets et lisant les données les concernant dans la base de données.
package services;

public class UserService {
}

package services;

public class CarService {
}
Cependant, une situation peut facilement se produire lorsque les données de la base de données sont dans un format, mais que nous en avons besoin dans un autre. Imaginez que la date de naissance de l'utilisateur dans la base de données soit stockée au format TIMESTAMP WITH TIME ZONE...
2014-04-04 20:32:59.390583+02
...nous avons plutôt besoin de l'objet le plus simple - java.util.Date. Pour cela, nous pouvons créer servicesune classe spéciale à l'intérieur du package Mapper. Il sera chargé de convertir les données de la base de données en objets Java que nous connaissons. Une classe d'assistance simple. Nous créons généralement toutes les classes en tant que public class ClassName, mais ce n'est pas nécessaire. Nous pouvons déclarer notre classe d'assistance simplement comme class Mapper. Dans ce cas, il fait toujours son travail, mais n'est visible par personne extérieure au package services!
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
Et c'est en fait la bonne logique : pourquoi quelqu'un en dehors du package verrait-il une classe auxiliaire qui ne fonctionne qu'avec les classes du même package ?

modificateur public

Et dernier sur la liste, mais non le moindre : le modificateur public! Vous l'avez rencontré le premier jour de vos études à JavaRush, en lançant public static void main(String[] args). Modificateurs d'accès.  Privé, protégé, par défaut, public - 4 Maintenant que vous avez étudié les cours sur les interfaces, son objectif est évident pour vous :) Après tout, publicil a été créé pour apporter quelque chose aux utilisateurs. Par exemple, l'interface de votre programme. Disons que vous avez écrit un programme de traduction capable de traduire du texte russe vers l'anglais. Vous avez créé une méthode translate(String textInRussian)dans laquelle la logique nécessaire est implémentée. Vous avez marqué cette méthode avec le mot public, et elle fera désormais partie de l'interface :
public class Translator {

   public String translate(String textInRussian) {

       // translates text from Russian to English
   }
}
Vous pouvez associer un appel à cette méthode au bouton « traduire » sur l'écran du programme - et c'est tout ! N’importe qui peut l’utiliser. Les parties du code marquées du modificateur publicsont destinées à l'utilisateur final. Pour donner un exemple concret, privatece sont tous les processus qui se produisent à l'intérieur du téléviseur lorsqu'il fonctionne, et publicce sont les boutons de la télécommande du téléviseur avec lesquels l'utilisateur peut le contrôler. En même temps, il n'a pas besoin de savoir comment fonctionne le téléviseur et comment il fonctionne. La télécommande est un ensemble publicde méthodes : on(), off(), nextChannel(), previousChannel(), increaseVolume(), decreaseVolume()etc.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION