CIAO! Nella lezione di oggi, conosceremo il concetto di modificatori di accesso e prenderemo in considerazione esempi su come lavorare con essi. Naturalmente, dire "fai conoscenza" non è del tutto corretto: conosci già la maggior parte di loro dalle lezioni precedenti. Per ogni evenienza, rinfreschiamo la memoria del punto più importante. I modificatori di accesso sono spesso parole chiave che regolano l'accesso a diverse parti del codice. Perché "il più delle volte"? Perché uno di questi è impostato di default senza l'uso di una parola chiave :) Java ha quattro modificatori di accesso. Li elenchiamo in ordine dal più restrittivo al più "indulgente":
private è il modificatore di accesso più restrittivo. Limita la visibilità di dati e metodi all'interno di una singola classe. Conosci questo modificatore dalla lezione su getter e setter. Ricordi questo esempio?
i campi e le modalità contrassegnate dal modificatore di accesso protetto :
Ora che hai studiato la lezione sulle interfacce, il suo scopo ti è ovvio :) Dopotutto, il public modificatore è stato creato per dare qualcosa agli utenti. Ad esempio, l'interfaccia del tuo programma. Supponi di aver scritto un programma di traduzione in grado di tradurre il testo russo in inglese. Hai creato un metodo translate(String textInRussian) che implementa tutta la logica necessaria. Hai contrassegnato questo metodo con la parola public e ora fa parte dell'interfaccia:
- privato;
- predefinito (pacchetto visibile);
- protetto;
- pubblico.
Il modificatore privato
![Modificatori di accesso. Privato, protetto, predefinito, pubblico - 2](https://cdn.codegym.cc/images/article/e72295b4-f185-452c-a525-491289973eb0/800.jpeg)
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 considerato in una lezione precedente. Abbiamo commesso un grave errore qui: rendiamo pubblici i nostri dati, il che ha consentito agli altri programmatori di accedere direttamente ai campi e modificarne i valori. Inoltre... questi valori sono stati assegnati senza alcun controllo. Ciò significa che il nostro programma potrebbe creare un gatto chiamato "" con un'età di -1000 anni e un peso di 0. Per risolvere questo problema, abbiamo utilizzato getter e setter e anche il modificatore private per limitare l'accesso ai dati.
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) {
// input parameter check
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
// input parameter check
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
// input parameter check
this.weight = weight;
}
}
Fondamentalmente, limitare l'accesso ai campi e implementare getter e setter sono gli esempi più comuni di come privatoverrebbe utilizzato nel lavoro reale. In altre parole, lo scopo principale di questo modificatore è ottenere l'incapsulamento in un programma. Questo non si applica solo ai campi, comunque. Immagina che nel tuo programma ci sia un metodo che implementa alcune funzionalità MOLTO complesse. Cosa possiamo suggerire come esempio? Diciamo che il tuo metodo readDataFromCollider() accetta come input un indirizzo dati, legge i dati dal Large Hadron Collider in formato byte, converte questi dati in testo, li scrive in un file e li stampa. Anche una descrizione del metodo sembra spaventosa, per non parlare del codice :) Per rendere il codice più leggibile, sarebbe meglio non scrivere tutta la complessa logica del metodo in un unico posto. Invece, dovremmo suddividere la funzionalità in metodi separati. Ad esempio, readByteData()Il metodo è responsabile della lettura dei dati, il metodo convertBytesToSymbols() converte i dati letti dal collisore in testo, il metodo saveToFile() salva il testo ricevuto in un file e il metodo printColliderData() stampa il nostro file di dati. Alla fine, il nostro metodo readDataFromCollider() sarà 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) {
// Converts bytes to characters
}
public File saveToFile(String[] colliderData) {
// Saves read data to a file
}
public void printColliderData(File fileWithColliderData) {
// Prints data from the file
}
}
Tuttavia, come ricorderete dalla lezione sulle interfacce, l'utente ha accesso solo all'interfaccia esterna. E i nostri 4 metodi non ne fanno parte. Sono metodi di supporto: li abbiamo creati per migliorare la leggibilità del codice e per non stipare quattro compiti diversi in un unico metodo. Non è necessario concedere all'utente l'accesso a questi metodi. Se gli utenti hanno accesso al metodo convertBytesToSymbols() quando lavorano con il collisore, molto probabilmente saranno semplicemente confusi dal metodo e si chiederanno a cosa serva. Quali byte vengono convertiti? Da dove provengono? Perché convertirli in testo? La logica eseguita in questo metodo non fa parte dell'interfaccia esposta all'utente. Solo readDataFromCollider()Il metodo fa parte dell'interfaccia. Quindi cosa facciamo con questi quattro metodi "interni"? Giusto! Usa il modificatore privato per limitare l'accesso ad essi. Ciò consente loro di svolgere serenamente il proprio lavoro all'interno della classe senza confondere l'utente, che non ha bisogno di conoscere la logica di ogni singolo metodo.
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) {
// Converts bytes to characters
}
private File saveToFile(String[] colliderData) {
// Saves read data to a file
}
private void printColliderData(File fileWithColliderData) {
// Prints data from the file
}
}
Il modificatore protetto
Il successivo modificatore più restrittivo è protected . Saranno visibili![Modificatori di accesso. Privato, protetto, predefinito, pubblico - 3](https://cdn.codegym.cc/images/article/38e389ae-5c1f-424a-aa60-7573885f5ed0/800.jpeg)
- all'interno di tutte le classi incluse nello stesso pacchetto del nostro;
- all'interno di tutte le classi che ereditano la nostra classe.
public abstract class AbstractSecretAgent {
public static int agentCount = 0;
}
Ma i nostri agenti sono segreti! Ciò significa che loro e nessun altro dovrebbero sapere quanti di loro esistono. Possiamo facilmente aggiungere il modificatore protected al campo agent_counter . Quindi le istanze di altre classi di agenti segreti e altre classi situate nel nostro pacchetto top_secret possono ottenere il suo valore.
public abstract class AbstractSecretAgent {
protected static int agent_counter = 0;
}
E questo è il tipo di attività specializzata che richiede il modificatore protected :)
Il modificatore visibile del pacchetto
Il prossimo nell'elenco è il modificatore predefinito , noto anche come modificatore visibile del pacchetto . Non è indicato da una parola chiave, poiché Java lo applica per impostazione predefinita a tutti i campi e metodi. Se scrivi quanto segue nel tuo codice:
int x = 10
la variabile x avrà accesso visibile a questo pacchetto . È facile ricordare cosa fa. Fondamentalmente, default = eredità protetta :) Come il modificatore protected , la sua applicazione è limitata. Molto spesso, l'accesso predefinito viene utilizzato in un pacchetto che ha alcune classi di utilità che non implementano la funzionalità di tutte le altre classi nel pacchetto. Facciamo un esempio. Immagina di avere un pacchetto di "servizi". Contiene varie classi che lavorano con un database. Ad esempio, c'è una classe UserService che legge i dati utente dal database, un CarServiceclasse che legge i dati dell'auto dallo stesso database e altre classi, ognuna delle quali lavora con tipi specifici di oggetti e legge i dati corrispondenti dal database.
package services;
public class UserService {
}
package services;
public class CarService {
}
Ma sarebbe facile per i dati nel database essere in un formato e ne abbiamo bisogno in un altro. Immagina che le date di nascita degli utenti nel database siano memorizzate come <TIMESTAMP WITH TIME ZONE>...
2014-04-04 20:32:59.390583+02
... e invece abbiamo bisogno dell'oggetto più semplice: un java.util.Date . Per risolvere questo problema, all'interno del pacchetto dei servizi , possiamo creare una speciale classe Mapper . Sarà responsabile della conversione dei dati dal database nei nostri oggetti Java familiari. Una semplice classe di aiuto. Di solito dichiariamo tutte le classi come public class ClassName , ma questo non è un requisito. Possiamo dichiarare la nostra classe helper semplicemente come class Mapper . In questo caso fa ancora il suo lavoro, ma non è visibile a nessuno al di fuori del pacchetto di servizi !
package services;
class Mapper {
}
package services;
public class CarService {
Mapper mapper;
}
Ed ecco il ragionamento di base: perché qualcuno al di fuori di un pacchetto dovrebbe vedere una classe helper che funziona solo con le classi in quel pacchetto?
Il modificatore pubblico
E, ultimo ma non meno importante, il modificatore pubblico ! Hai incontrato questo modificatore il tuo primo giorno di studio su CodeGym la prima volta che hai eseguito public static void main(String[] args) .![Modificatori di accesso. Privato, protetto, predefinito, pubblico - 4](https://cdn.codegym.cc/images/article/c228e136-0fc7-48eb-a9ab-9acf4d8edcc1/800.jpeg)
public class Translator {
public String translate(String textInRussian) {
// Translates text from Russian to English
}
}
Puoi associare questo metodo al pulsante "Traduci" sullo schermo e il gioco è fatto! Chiunque può usarlo. Le parti di codice contrassegnate con il modificatore public sono destinate all'utente finale. Fornendo un esempio di vita reale, privato è per tutti i processi che si verificano all'interno di una TV, ma pubblico è per i pulsanti del telecomando utilizzati per gestire la TV. Inoltre, l'utente non ha bisogno di sapere come è costruito o come funziona il televisore. Il telecomando è l'insieme dei metodi pubblici : on() , off() , nextChannel() , previousChannel() , augmentVolume() , diminuzioneVolume() ecc. Per rafforzare ciò che hai imparato, ti suggeriamo di guardare una lezione video dal nostro corso Java
GO TO FULL VERSION