Corso di Java

Ereditarietà e gerarchie di classi I

 

Dopo aver lavorato pazientemente alla creazione della nostra prima classe in Java, dobbiamo per un attimo fermarci e - ahinoi! – andare ad approfondire qualche altro piccolo concetto teorico.
Nella quarta lezione, abbiamo saputo che i nostri amici Bill Gates e Linus Torvalds appartengono alla classe “Uomo”, ma appartengono anche alla classe “Esseri viventi”, della quale fanno parte anche Rin Tin Tin e Lassie, che a loro volta sono istanze della classe “Cane”.
Vista così, la questione sembra piuttosto ingarbugliata e confusa, e correremmo il rischio di fare assegnamenti sbagliati!
Tuttavia non possiamo fare a meno di notare che esiste una certa relazione tra i nostri quattro amici e che questa relazione ha una particolarità: infatti possiamo dire che un uomo è un essere vivente, che un cane è anch’esso un essere vivente, ma non è corretto affermare che un essere vivente è un cane.
La differenza tra “Essere vivente” e “Uomo” sta nel livello di astrazione.

La prima rappresenta, infatti, una generalizzazione della seconda e comprende altre classi oltre ad essa (come ad es. la classe “Cane”), mentre la seconda rappresenta una specializzazione della prima.



Sia il cane che l’uomo hanno tutte le caratteristiche dell’essere vivente, ovvero entrambi vivono, in qualche modo si nutrono, etc.; si dice che essi ereditano dalla classe “Essere vivente” gli attributi e i comportamenti.
E proprio l’ereditarietà è uno dei concetti base dell’OOP e, di conseguenza, anche di Java.
Non è difficile comprendere che l’ereditarietà si può sviluppare in una gerarchia molto complessa, che si sviluppa a partire da una radice (che rappresenta il massimo grado di astrazione), per poi diramarsi via via in una struttura ad albero, in cui ogni ramo rappresenta una specializzazione del nodo precedente.

La figura successiva ci mostra un esempio di quanto espresso sinora.



In Java, una classe che eredita le caratteristiche da un’altra classe viene chiamata sottoclasse, mentre la classe che fornisce l’eredità è detta superclasse.
Una classe può avere una sola superclasse e un numero illimitato di sottoclassi.
Una sottoclasse eredita tutti gli attributi e i metodi della relativa superclasse, e può definirne di propri in aggiunta o in sostituzione a quelli della propria superclasse.

Vediamo di chiarire tutto con un esempio pratico.
Definiamo una classe “Uomo” molto semplice:

class Uomo {
    private String nome;
    private byte eta;
    private String professione;

    public String getNome() {
        return nome;
    }

    public String getProfessione() {
        return professione;
    }

    public byte getEta() {
        return eta;
    }

    public void dice(String parole) {
        System.out.println(nome + ": - " + parole);
    }
}


Per creare una sottoclasse a partire da questa, occorre utilizzare la parola chiave extends.

Se volessimo ad es. definire una classe “UomoDAffari”, potremmo scrivere:

class UomoDAffari extends Uomo {
    private String titoloDiStudio;
    private long liquidita;

    public String getTitoloDiStudio() {
        return titoloDiStudio;
    }
   
    public long getLiquidita() {
        return liquidita;
    }

    public void dice(String parole) {
        System.out.println(titoloDiStudio + ‘ ‘ + nome + ": - " + parole);
    }
}


Questa classe contiene gli attributi nome, eta, professione (ereditati dalla classe Uomo) e gli attributi titoloDiStudio e liquidita, che sono invece specifici di essa.

Inoltre su un oggetto di tipo UomoDAffari possiamo invocare i metodi getNome(), getEta(), getProfessione(), getLiquidita() e dice(String).
Quest’ultimo metodo è stato definito sia nella superclasse “Uomo” che nella sottoclasse “UomoDAffari”.
Nella prima, esegue la stampa a video della variabile nome, seguita dalla stringa “: - “ e da una stringa passatagli come parametro; nella seconda, stampa innanzitutto il titolo di studio, poi un carattere di spazio seguito dalla variabile nome, e dopo la stringa “: - “ seguita da un’altra stringa passatagli come parametro.
Questa possibilità di ridefinizione dei metodi è molto interessante; più avanti vedremo in dettaglio come funziona.

 

Torna all'indice Generale del corso di Corso di Java di Software Planet