Se avete provato a compilare gli esempi della volta scorsa, ossia la classe Uomo e la classe UomoDAffari, vi sarete trovati di fronte ad almeno due errori del compilatore di questo tipo:
Come si può vedere, il compilatore Java ci da diverse informazioni
riguardo ad ogni errore commesso:
il file sorgente in cui lerrore è stato rilevato;
il numero della riga;
il tipo dellerrore;
viene stampata lintera riga e messo un simbolo (^) nel punto
in cui lerrore è stato rilevato.
La prima informazione sembrerebbe inutile, tuttavia ha un senso,
perché prima di compilare il sorgente indicato alla linea di comando
(nel nostro caso UomoDAffari.java), Java cerca tutti i bytecode
relativi alle classi utilizzate nel sorgente specificato, se non
li trova cerca i sorgenti e (se li trova) li compila prima di quello
da noi indicato.
In questo caso, la compilazione del sorgente Uomo.java (se non
era stata fatta in precedenza) è andata a buon fine e non ha dato
luogo ad alcun errore.
Il primo errore rilevato al compilatore è No constructor matching
Uomo() found in class Uomo con riferimento al sorgente UomoDAffari.java.
La cosa può, a prima vista, sembrare piuttosto strana; tuttavia
è chiaro che il problema è legato ai costruttori.
Abbiamo detto che non è necessario specificare un costruttore per
una classe.
Quando si omette di definirlo esplicitamente, il compilatore si
occupa di crearne automaticamente uno di default senza argomenti,
cosicché per creare un oggetto di quella classe bisogna indicare
il nome della classe, seguito da due parentesi tonde (aperta e chiusa)
del tipo:
NomeClasse oggetto = new NomeClasse();
Questa istruzione crea un nuovo oggetto e invoca il costruttore
di default, anche se non ne è stato definito uno in maniera esplicita;
senza di esso non avremmo alcun metodo da chiamare per istanziare
il nostro oggetto.
Teniamo presente che, una volta definito almeno un costruttore,
il compilatore non creerà automaticamente quello di default (ossia
senza parametri), per cui non potremo creare un oggetto della classe
Uomo semplicemente scrivendo:
Uomo macho = new Uomo();
Poiché non abbiamo indicato alcun costruttore per la classe UomoDAffari,
il compilatore ne costruisce uno di default e salta fuori un problema
dovuto allereditarietà, che ci spiega il perché del primo
errore.
Infatti quando si istanzia un oggetto di una sottoclasse, esso
contiene quello che potremmo definire un sottooggetto
della superclasse, che è a tutti gli effetti un oggetto della classe
padre (parlare di superclasse o di classe padre è la stessa cosa).
E essenziale che il sottooggetto della classe
padre sia inizializzato correttamente e ciò lo si può fare solamente
effettuando linizializzazione nel costruttore, per mezzo di
uninvocazione del costruttore della superclasse.
Java inserisce automaticamente nel costruttore della classe figlio
una chiamata al costruttore senza argomenti della classe padre.
Ecco la causa dellerrore: il costruttore di default creato
dal compilatore deve eseguire al suo interno linvocazione
al costruttore Uomo() che non è presente nella superclasse, per
cui la compilazione non può avere luogo.
Due sono le soluzioni possibili:
possiamo definire esplicitamente un costruttore senza argomenti
per la classe Uomo();
possiamo definire esplicitamente un costruttore per la classe UomoDAffari,
che invochi esplicitamente il costruttore della superclasse.
La prima soluzione non ha senso per il nostro esempio (non sarebbe
carino creare un uomo con un nome di default), per cui opteremo
per la seconda e inseriremo nel codice della sottoclasse il seguente
costruttore:
UomoDAffari (String nome,
byte eta, String prof, String tds, long l) {
super(nome, eta, prof);
titoloDiStudio = tds;
liquidita = l;
}
Avete notato qualcosa di nuovo?
Ebbene, la parola chiave super viene utilizzata per riferirsi
alla superclasse della classe attuale.
Con la prima istruzione non facciamo altro che invocare uno dei
costruttori della classe Uomo, passandogli come parametri
i valori opportuni, mentre le due istruzioni successive servono
ad inizializzare gli attributi specifici della nostra sottoclasse.
Se riproviamo a compilare il primo errore sarà sparito; vedremo
come correggere il secondo nella prossima puntata.
Torna all'indice Generale del corso di Corso di Java di Software Planet