Ciao! La risposta breve è: si, in ogni metodo che specifica un valore di ritorno devi SEMPRE mettere un return, anche se il metodo è overriden.
Il motivo è che, di fatto, si tratta di due metodi diversi, un po' come se avessi il seguente esempio:
public int moltiplica(int a, int b) {
int result = 0;
for (int i=0; i<b; i++) {
result = somma(result,a);
}
// Cosa restituisco?
}
Cioè è vero che il metodo "somma" restituisce un valore, ma questo non dice nulla su ciò che dovrà restituire il metodo "moltiplica", per il quale dovrai esplicitamente mettere un valore di return.
Allo stesso modo, se non metti il return, la classe figlia non sa cosa restituire al chiamante, anche se la classe madre restituisce qualcosa.
Inoltre vorrei farti notare l'ordine in cui hai ridefinito il metodo:
public static int metodoDaSovrascrivere(...){
variante
super.metodoDellaSuperClasse(..)
}
Ovvero richiami il metodo della superclasse DOPO aver fatto delle modifiche. Questa cosa di per sé non è sbagliata, ma guarda le seguenti classi:
public class Madre {
protected Counter c;
public int metodo() {
c = new Counter();
return c.getCount();
}
}
public class Figlia extends Madre {
@Override
public int metodo() {
c.increment(); // NullPointerException
return super.metodo();
}
}
Se provi ad eseguire questo codice in un main (supponendo di aver definito da qualche altra parte la classe Counter) otterrai un NullPointerException. Infatti nel metodo della classe Figlia tenti di accedere ad una variabile che non è ancora stata inizializzata, in quanto l'inizializzazione è "a carico" del metodo della classe Madre, che però richiami DOPO aver tentato di modificare la variabile. Di conseguenza in generale l'ordine in cui esegui il codice Madre/Figlia è importante e fa la differenza.
Nota che in questo caso specifico te ne accorgi facilmente a runtime perché viene sollevata un'eccezione, ma potresti avere cose più subdole, tipo:
public class Madre {
protected Counter c;
public Madre() {
c = new Counter();
}
public int metodo() {
c.setCount(0);
return c.getCount();
}
}
public class Figlia extends Madre {
public Figlia() {
super();
}
@Override
public int metodo() {
c.setCount(10);
return super.metodo();
}
}
public class Main {
public static void main(String[] args) {
Figlia f = new Figlia();
System.out.println(f.metodo());
}
}
In questo caso non viene lanciata nessuna eccezione, ma la modifica "c.setCount(10)" viene sovrascritta dal metodo della classe Madre!