JavaRush /Java Blog /Random-IT /Modificatori di accesso. Privato, protetto, predefinito, ...

Modificatori di accesso. Privato, protetto, predefinito, pubblico

Pubblicato nel gruppo Random-IT
Ciao! Nella lezione di oggi conosceremo il concetto di " modificatori di accesso " e vedremo esempi di come lavorare con essi. Modificatori di accesso.  Privato, protetto, predefinito, pubblico - 1Anche se la parola "facciamo conoscenza" non sarà del tutto corretta: ne conosci già la maggior parte dalle lezioni precedenti. Per ogni evenienza, rinfreschiamo la memoria sulla cosa principale. I modificatori di accesso sono spesso parole chiave che regolano il livello di accesso a diverse parti del codice. Perché "più spesso"? Perché uno di questi è impostato di default e non è indicato da una parola chiave :) Ci sono un totale di quattro modificatori di accesso in Java. Li elenchiamo in ordine dal più rigoroso al più “soft”:
  • privato;
  • protetto;
  • default(pacchetto visibile);
  • pubblico
Diamo un'occhiata a ciascuno di essi, decidiamo quando possono esserci utili e forniamo esempi :)

Modificatore privato

Modificatori di accesso.  Privato, protetto, predefinito, pubblico - 2Private— il modificatore di accesso più restrittivo. Limita la visibilità dei dati e dei metodi all'interno di una singola classe. Conosci questo modificatore dalla lezione su getter e setter. Ricordi questo esempio?
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;
   }
}
Lo abbiamo visto in uno degli articoli precedenti. Qui abbiamo commesso un grave errore: abbiamo aperto i nostri dati, in seguito ai quali altri programmatori hanno avuto accesso diretto ai campi della classe e alla modifica dei loro valori. Inoltre, questi valori sono stati assegnati senza controlli, per cui nel nostro programma è possibile creare un gatto con un'età di -1000 anni, un nome "" e un peso pari a 0. Per risolvere questo problema, noi getter e setter utilizzati e anche accesso limitato ai dati utilizzando un modificatore 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;
   }
}
In realtà, limitare l'accesso ai campi e implementare getter-setter è l'esempio più comune di utilizzo privatenel lavoro reale. Cioè, implementare l'incapsulamento in un programma è lo scopo principale di questo modificatore. A proposito, questo non vale solo per i campi. Immagina che nel tuo programma ci sia un metodo che implementa alcune funzionalità MOLTO complesse. Per usare questo come esempio... Diciamo che il tuo metodo readDataFromCollider()prende un indirizzo con dati come input, legge i dati dal Large Hadron Collider in formato byte, converte questi dati in testo, li scrive in un file e lo stampa. Anche la descrizione del metodo sembra inquietante, per non parlare del codice :) Per aumentare la leggibilità del codice, sarebbe bene non scrivere la complessa logica del metodo in un unico posto, ma, al contrario, interromperne la funzionalità in metodi separati. Ad esempio, il metodo readByteData()è responsabile della lettura dei dati, convertBytesToSymbols()della conversione dei dati letti dal collisore in testo, saveToFile()del salvataggio del testo risultante in un file e printColliderData()della stampa del nostro file di dati. Il metodo readDataFromCollider()finirebbe per essere molto più semplice:
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
   }
}
Tuttavia, come ricorderete dalla lezione sulle interfacce, l'utente ha accesso solo all'interfaccia finale. E i nostri 4 metodi non ne fanno parte. Sono ausiliari : li abbiamo creati per migliorare la leggibilità del codice ed evitare di stipare quattro attività diverse in un unico metodo. Non è necessario fornire all'utente l'accesso a questi metodi. Se un utente ha accesso al metodo mentre lavora con un collisore convertBytesToSymbols(), molto probabilmente semplicemente non capirà cos'è questo metodo e perché è necessario. Quali byte vengono convertiti? Da dove provengono? Perché convertirli in testo? La logica eseguita in questo metodo non fa parte dell'interfaccia utente. Solo il metodo readDataFromCollider()fa parte dell'interfaccia. Cosa fare con questi quattro metodi "interni"? Giusto! Limitarne l'accesso con un modificatore private. In questo modo possono svolgere facilmente il loro lavoro all'interno della classe e non confondere l'utente, che non ha bisogno della logica di ciascuno di essi separatamente.
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
   }
}

Modificatore protetto

Il successivo modificatore di accesso più restrittivo è protected. Modificatori di accesso.  Privato, protetto, predefinito, pubblico - 3 I campi e i metodi designati con il modificatore di accesso protectedsaranno visibili:
  • all'interno di tutte le classi che fanno parte dello stesso pacchetto del nostro;
  • all'interno di tutte le classi successive della nostra classe.
È immediatamente difficile immaginare quando ciò potrebbe essere necessario. Non stupitevi: protectedi casi di applicazione sono molti meno di private, e sono specifici. Immagina di avere una classe astratta AbstractSecretAgentche denota un agente segreto di un servizio speciale, nonché un pacchetto top_secretche contiene questa classe e i suoi discendenti. Da esso vengono ereditate le classi concrete - FBISecretAgent, MI6SecretAgent, MossadSecretAgentecc . All'interno della classe astratta vogliamo implementare un contatore dell'agente. Quando un nuovo oggetto agente viene creato da qualche parte nel programma, aumenterà.
package top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Ma i nostri agenti sono segreti! Ciò significa che solo loro e nessun altro dovrebbero conoscere il loro numero. Possiamo facilmente aggiungere un modificatore protectedal campo agentCounte quindi sia gli oggetti di altre classi di agenti segreti, sia quelle classi che si trovano nel nostro pacchetto "segreto", possono ottenere il suo valore top_secret.
public abstract class AbstractSecretAgent {

   protected static int agentCount = 0;
}
È per compiti così specifici che è necessario un modificatore protected:)

modificatore visibile del pacchetto

Il prossimo nella nostra lista è il modificatore defaulto, come viene anche chiamato, package visible. Non è indicato da una parola chiave perché è impostato di default in Java per tutti i campi e metodi. Se scrivi nel tuo codice -
int x = 10;
... la variabile xavrà lo stesso package visibleaccesso. Se un metodo (o una variabile) non è contrassegnato con alcun modificatore, è considerato contrassegnato con il "modificatore predefinito". Le variabili o i metodi con tale modificatore (cioè senza alcuno) sono visibili a tutte le classi del pacchetto in cui sono dichiarati. E solo a loro. I suoi usi sono limitati, proprio come il modificatore protected. Molto spesso, default-access viene utilizzato in un pacchetto in cui sono presenti alcune classi di utilità che non implementano la funzionalità di tutte le altre classi in questo pacchetto. Facciamo un esempio. Immaginiamo di avere un pacchetto " servizi ". Al suo interno ci sono varie classi che lavorano con il database. Ad esempio, esiste una classe UserServiceche legge i dati dell'utente da un database, una classe CarServiceche legge i dati sulle automobili dallo stesso database e altre classi, ognuna delle quali lavora con il proprio tipo di oggetti e legge i dati su di essi dal database.
package services;

public class UserService {
}

package services;

public class CarService {
}
Tuttavia, può facilmente verificarsi una situazione in cui i dati nel database sono in un formato, ma ne abbiamo bisogno in un altro. Immagina che la data di nascita dell'utente nel database sia memorizzata nel formato TIMESTAMP WITH TIME ZONE...
2014-04-04 20:32:59.390583+02
...abbiamo invece bisogno dell'oggetto più semplice - java.util.Date. A questo scopo possiamo creare servicesuna classe speciale all'interno del pacchetto Mapper. Sarà responsabile della conversione dei dati dal database negli oggetti Java che conosciamo. Una semplice classe di aiuto. Di solito creiamo tutte le classi come public class ClassName, ma ciò non è necessario. Possiamo dichiarare la nostra classe helper semplicemente come class Mapper. In questo caso fa comunque il suo lavoro, ma non è visibile a nessuno al di fuori della confezione services!
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
E questa, in effetti, è la logica corretta: perché qualcuno all'esterno del pacchetto dovrebbe vedere una classe ausiliaria che funziona solo con le classi dello stesso pacchetto?

modificatore pubblico

E ultimo della lista, ma non meno importante, il modificatore public! Lo hai incontrato il primo giorno di studio a JavaRush, lanciando public static void main(String[] args). Modificatori di accesso.  Privato, protetto, predefinito, pubblico - 4 Ora che hai studiato le lezioni sulle interfacce, il suo scopo ti è chiaro :) Dopotutto, publicè stato creato per dare qualcosa agli utenti. Ad esempio, l'interfaccia del tuo programma. Supponiamo che tu abbia scritto un programma di traduzione e che possa tradurre il testo russo in inglese. Hai creato un metodo translate(String textInRussian)all'interno del quale viene implementata la logica necessaria. Hai contrassegnato questo metodo con la parola publice ora diventerà parte dell'interfaccia:
public class Translator {

   public String translate(String textInRussian) {

       // translates text from Russian to English
   }
}
Puoi associare una chiamata a questo metodo con il pulsante "traduci" sulla schermata del programma - e il gioco è fatto! Chiunque può usarlo. Le parti del codice contrassegnate con il modificatore publicsono destinate all'utente finale. Per fare un esempio dalla vita, privatequesti sono tutti i processi che avvengono all'interno del televisore mentre funziona, e publicquesti sono i pulsanti sul telecomando del televisore con cui l'utente può controllarlo. Allo stesso tempo, non ha bisogno di sapere come funziona la TV e come funziona. Il telecomando è un insieme publicdi metodi: on(), off(), nextChannel(), previousChannel(), increaseVolume(), decreaseVolume()ecc.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION