Lezione di Java 19 – L’operatore instanceof

Indice Lezione PrecedenteLezione Successiva


Con l’introduzione del polimorfismo potrebbe essere utile conoscere il tipo dell’oggetto con cui si ha a che fare. Ad esempio se dobbiamo utilizzare un determinato metodo o far riferimento ad uno specifico attributo della sottoclasse, avremo bisogno dell’operatore instanceof. Quest’operatore indica se l’oggetto è “istanza di” un determinato tipo. La sintassi prevede la seguente dichiarazione:

<riferimento> instanceof <tipo_riferimento>

Facendo sempre riferimento all’esempio della scorsa lezione sulle persone, avremo:

if (a instanceof Maschio) {
  // Abbiamo un maschio
}
else if (a instanceof Femmina) {
  // Abbiamo una femmina
} else {
  // Abbiamo una persona generica
}


Per poter accedere ai dati di una sottoclasse c’è bisogno di un cast del riferimento. In Java qualsiasi cast di riferimento da una sottoclasse ad una superclasse (upcast) funziona sempre, non c’è bisogno di un cast esplicito:

Maschio a = new Maschio();
Persona b = a; // Cast implicito

se invece si passa da una sottoclasse ad una superclasse il cast di riferimento è obbligatorio (downcast):

Persona a = new Maschio();
Maschio b = (Maschio) a;

Il casting è obbligatorio perchè essendo a tempo di compilazione il compilatore non può sapere che tipo di oggetto punta il riferimento, affida quindi tutto all’utente. Un successo a tempo di compilazione non preclude un errore a tempo di esecuzione. A tempo di compilazione il compilatore controlla solo se i riferimenti fanno parte della stessa gerarchia. Esempio: se A è superclasse di B e C, sottoclassi separate (disgiunte), avremo:

A a = new A();
B b = (B) a; // Ok, stessa gerarchia

C c = new C();
B b = (B) c; // Errore in compilazione, diversa gerarchia

A a = new C(); // Ok, superclasse
B b = (B) a; // Ok, in compilazione, errore in esecuzione (*)

(*) a e b sono tipi nelle stessa gerarchia quindi non avremo errori in compilazione, in esecuzione invece si, a fa riferimento ad un oggetto di gerarchia differente.

I cast servono a “svelare” metodi ed attributi prima nascosti. Supponiamo che la classe Maschio abbia un metodo setNumero:

Persona a = new Maschio();
a.setNumero(5); // Errore, a è di tipo Persona e non conosce nessun metodo chiamato setNumero

Maschio b = (Maschio) b; // Con un cast "sveliamo" attributi e metodi di Maschio

b.setNumero(5); // Ok, nessun problema

Nella prossima lezione tratteremo i modificati d’accesso in Java.

Ti piace l’articolo?
Diventa fan su Facebook
Indice Lezione PrecedenteLezione Successiva
Pubblicato in Guide, Guide, Java, Programmazione Taggato con: , , ,
4 comments on “Lezione di Java 19 – L’operatore instanceof
  1. Max scrive:

    Occhio, si scrive instanceof, con la “n” 🙂

  2. gingi scrive:

    Riguardo l’upcast avete scritto:

    ” Per poter accedere ai dati di una sottoclasse c’è bisogno di un cast del riferimento. In Java qualsiasi cast di riferimento da una sottoclasse ad una sottoclasse (upcast) questo funziona sempre, non c’è bisogno di un cast esplicito ”

    Mentre dovevate scrivere (credo sia un semplice errore di copia-incolla riguardo le parole ‘da una sottoclasse ad una sottoclasse’, ma per il resto l’upcast può servire, non è inutile…):

    Per poter accedere ai dati di una sottoclasse c’è bisogno di un cast del riferimento. In Java qualsiasi cast di riferimento da una sottoclasse ad una superclasse (upcast) questo funziona quasi sempre, cioè di solito non c’è bisogno di un cast esplicito, eccetto che per casi particolari, come nel caso dell’uso di un metodo appartente alla stessa classe, ma che , per via di un overriding su tale metodo, può richiedere come argomenti delle variabili di sottoclassi diverse della stessa superclasse, come ad esempio:

    posto che abbiamo due sottoclassi di ‘Poligono’, le quali si chiamano ‘Triangolo’ e ‘Quadrato’…
    e voglio calcolarne il perimetro col metodo calcPerim()

    allora nel caso del quadrato dev’essere:
    public float calcPerim(Quadrato quadrato) {..}

    ma nel caso del triangolo dev’essere:
    public float calcPerim(Triangolo triangolo) {..}

    allora sull’oggetto della superclasse ‘Poligono’ dovrò eseguire per forza i seguenti upcast:

    per il quadrato:
    prima controllo con degli if che l’oggetto passato come argomento al metodo sia di tipo ‘Quadrato’, e poi lo do in pasto al metodo:
    public float calcPerim((Quadrato) poligono) {..}

    e per il triangolo:
    prima controllo con degli if che l’oggetto passato come argomento al metodo sia di tipo ‘Triangolo’, e poi lo do in pasto al metodo:
    public float calcPerim((Triangolo) poligono) {..}

    ottendendo così il risultato del calcolo del perimetro per un poligono di tipo quadrato e per un poligono di tipo triangolo, che ovviamente saranno dichiarati come metodi diversi all’interno del loro corpo del codice…

  3. gingi scrive:

    scusate ho sbagliato commento, non rendetelo in considerazione….

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*