CodeGym /Corsi /JAVA 25 SELF /Modificatori di accesso

Modificatori di accesso

JAVA 25 SELF
Livello 15 , Lezione 1
Disponibile

1. Panoramica dei modificatori di accesso

In Java esistono quattro livelli di accesso per classi, campi, metodi e costruttori:

Modificatore Dove è disponibile?
public
Ovunque: all'interno della classe, in altre classi, in altri pacchetti
protected
All'interno della classe, nelle sottoclassi (ereditarie), nelle altre classi dello stesso pacchetto
(package-private)
Solo all'interno del pacchetto (se il modificatore non è specificato esplicitamente)
private
Solo all'interno della classe corrente

Vediamo ciascuno più nel dettaglio — con esempi, qualche battuta e colpi di scena inaspettati.

public — accesso pubblico

public — è come un annuncio a tutto il mondo: «Ingresso consentito a tutti!». Se una classe, un campo, un metodo o un costruttore è dichiarato public, è accessibile da qualsiasi altra classe, anche da un altro pacchetto.

Esempio:

public class Cat {
    public String name;
    public void sayMeow() {
        System.out.println("Miao!");
    }
}

Si può accedere a questa classe e ai suoi campi/metodi da qualsiasi luogo. È comodo se vuoi che la tua classe sia disponibile a tutti: ad esempio, se stai scrivendo una libreria.

Ma! I campi pubblici non sono sempre una buona idea (vedi la lezione precedente). Di solito si rendono pubblici solo i metodi che devono essere accessibili dall'esterno, mentre i campi quasi sempre restano private.

private — accesso solo all'interno della classe

private — è come una cassaforte con combinazione: nessuno, tranne la stessa classe, può accedere a questi membri. Perfino le sottoclassi non vedono i campi e i metodi privati!

Esempio:

public class Cat {
    private String secretName;

    public void setSecretName(String name) {
        secretName = name;
    }

    public String getSecretName() {
        return secretName;
    }
}

Qui secretName non può essere letto o modificato direttamente da un'altra classe. Solo Cat stesso può farlo (o i suoi metodi). Questa è la base dell'incapsulamento: nascondiamo i dettagli interni e forniamo l’accesso ad essi solo tramite metodi.

protected — accesso protetto

protected — è come un pass VIP: accesso consentito alla classe, alle sue sottoclassi (anche se si trovano in altri pacchetti) e a tutte le classi all'interno dello stesso pacchetto.

Esempio:

public class Animal {
    protected int age;

    protected void growOlder() {
        age++;
    }
}

Ora qualsiasi classe che estende Animal potrà accedere al campo age e al metodo growOlder().

public class Cat extends Animal {
    public void haveBirthday() {
        growOlder();
        System.out.println("Il gatto ha compiuto " + age + " anni!");
    }
}

Inoltre, tutte le classi dello stesso pacchetto hanno accesso ai membri protected.

(package-private) — accesso all'interno del pacchetto

Se non specifichi affatto un modificatore di accesso, il membro della classe è considerato package-private (o «accesso predefinito»). È come una porta senza serratura, ma solo per i tuoi: accesso consentito solo alle classi dello stesso pacchetto.

Esempio:

class Dog {
    String name; // package-private
    void bark() { // package-private
        System.out.println("Bau!");
    }
}

La classe Dog, il suo campo name e il metodo bark() sono accessibili solo all'interno dello stesso pacchetto. Un tentativo di accedervi da un altro pacchetto causerà un errore di compilazione.

2. Applicazione dei modificatori a campi e metodi

Perché i campi sono quasi sempre private

I campi di una classe rappresentano il suo stato interno. Se li lasci pubblici, qualsiasi codice esterno potrà modificarli in qualunque momento. È come se permettessi a bambini sconosciuti di giocare con i tuoi mobili come fossero Lego: un giorno ti svegli e il frigorifero è capovolto in bagno.

Esempio di incapsulamento sbagliato:

public class Person {
    public String name;
    public int age;
}

Esempio di buon incapsulamento:

public class Person {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

I metodi (getter e setter) consentono di controllare come i campi possono essere modificati dal codice esterno. Ad esempio, puoi vietare un'età negativa.

Quando rendere i metodi public, protected o package-private

  • public — se il metodo deve essere accessibile a tutti. In genere è la funzionalità principale della classe.
  • protected — se il metodo serve solo alle sottoclassi o all'interno del pacchetto (ad esempio, metodi di supporto che possono essere utili nelle classi figlie).
  • package-private — se il metodo serve solo all'interno del pacchetto ma non deve essere accessibile dall'esterno (ad esempio, dettagli interni di implementazione).
  • private — se il metodo è usato solo all'interno della stessa classe (ad esempio, metodi di supporto per la logica interna).

Esempio:

public class BankAccount {
    private double balance;

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    protected void applyInterest() {
        balance *= 1.05;
    }

    void internalAudit() {
        // package-private: solo per le classi all'interno del pacchetto
    }

    private void logAction(String action) {
        // solo per le esigenze interne della classe
    }
}

3. Esempi di codice: una classe con diversi livelli di accesso

Creiamo una classe che ha di tutto: membri pubblici, privati, protetti e di pacchetto. Proviamo anche ad accedervi da altre classi e vediamo cosa succede.

package zoo;

public class Animal {
    public String publicName = "Disponibile a tutti";
    protected String protectedName = "Solo per le sottoclassi e il pacchetto";
    String packageName = "Solo per il pacchetto";
    private String privateName = "Solo per Animal";

    public void publicMethod() {
        System.out.println("Metodo pubblico");
    }

    protected void protectedMethod() {
        System.out.println("Metodo protetto");
    }

    void packageMethod() {
        System.out.println("Metodo di pacchetto");
    }

    private void privateMethod() {
        System.out.println("Metodo privato");
    }
}

Ora proviamo ad accedere a questi membri da un'altra classe nello stesso pacchetto:

package zoo;

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName);   // OK
        System.out.println(animal.packageName);     // OK
        System.out.println(animal.privateName);  // Errore: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                   // OK
        animal.packageMethod();                     // OK
        animal.privateMethod();                  // Errore: private
    }
}

Ora proviamo ad accedere a questi membri da un altro pacchetto:

package other;

import zoo.Animal;

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName); // Errore: protected
        System.out.println(animal.packageName);   // Errore: package-private
        System.out.println(animal.privateName);   // Errore: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                // Errore: protected
        animal.packageMethod();                  // Errore: package-private
        animal.privateMethod();                  // Errore: private
    }
}

Conclusione:

  • public — disponibile ovunque.
  • protected — disponibile all'interno del pacchetto e nelle sottoclassi (anche da altri pacchetti, se tramite ereditarietà).
  • package-private — solo all'interno del pacchetto.
  • private — solo all'interno della classe.

4. Best practice: come scegliere il modificatore di accesso

Minimizza la visibilità

Quanto meno codice può vedere il tuo campo o metodo, tanto meglio. Esponi solo ciò che serve davvero al codice esterno. Questo è il principio del privilegio minimo (principle of least privilege).

  • I campi dovrebbero quasi sempre essere private. Eccezioni — solo per vere costanti (public static final), ma ne parleremo meglio nelle prossime lezioni.
  • I metodi si rendono public solo se fanno parte dell'interfaccia esterna della classe.
  • I metodi di supporto (logica interna) — private.
  • Metodi per le sottoclassiprotected.
  • Metodi di servizio interni al pacchettopackage-private.

Perché è importante?

  • Qualsiasi modifica ai dettagli di implementazione può rompere il codice altrui, se i dettagli sono esposti.
  • La classe diventa più difficile da testare e mantenere.
  • Errori accidentali (ad esempio, modifiche scorrette a un campo) possono portare a bug.

A volte i principianti pensano: «Perché complicarsi la vita, rendiamo tutto public!» Ma poi, quando il progetto cresce, si ritrovano a riscrivere metà del programma solo perché qualcuno modificava direttamente i campi della classe.

5. Errori tipici nell'uso dei modificatori di accesso

Errore n. 1: Campi lasciati public o package-private per impostazione predefinita.
Se non specifichi un modificatore, il campo o il metodo sarà accessibile a tutte le classi all'interno del pacchetto. Questo può portare a situazioni inattese, se qualcuno inizia a cambiare direttamente i tuoi campi.

Errore n. 2: Tentativo di accedere a un membro private da un'altra classe.
Il compilatore non lo permette — otterrai un errore. Ma se decidi di aggirarlo tramite reflection (riflessione), benvenuto nel mondo di bug e crash inaspettati.

Errore n. 3: Troppo public.
Se dichiari tutto public, la classe assomiglia a una scatola aperta piena di cavi — chiunque può tirare quello sbagliato e rompere tutto.

Errore n. 4: Non usare protected per i metodi necessari solo alle sottoclassi.
Se un metodo serve solo per essere esteso nelle classi figlie, dichiaralo protected, non public.

Errore n. 5: Visibilità package-private implicita.
A volte ci si dimentica di specificare il modificatore e il metodo diventa accessibile a tutto il pacchetto. Può essere una sorpresa se pensavi che fosse private.

1
Compito
JAVA 25 SELF, livello 15, lezione 1
Bloccato
Leggere il nome sul biglietto da visita digitale 🃏
Leggere il nome sul biglietto da visita digitale 🃏
1
Compito
JAVA 25 SELF, livello 15, lezione 1
Bloccato
Calcolatrice magica con meccanismo segreto ➕
Calcolatrice magica con meccanismo segreto ➕
1
Compito
JAVA 25 SELF, livello 15, lezione 1
Bloccato
Assistenza interna nel team di sviluppo 🤝
Assistenza interna nel team di sviluppo 🤝
1
Compito
JAVA 25 SELF, livello 15, lezione 1
Bloccato
Gestione della biblioteca digitale: chi può fare cosa 🏛️
Gestione della biblioteca digitale: chi può fare cosa 🏛️
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION