Java - Sostituzione
Nel capitolo precedente abbiamo parlato di superclassi e sottoclassi. Se una classe eredita un metodo dalla sua superclasse, c'è la possibilità di sovrascrivere il metodo a condizione che non sia contrassegnato come finale.
Il vantaggio dell'override è: capacità di definire un comportamento specifico per il tipo di sottoclasse, il che significa che una sottoclasse può implementare un metodo di classe padre in base ai suoi requisiti.
In termini orientati agli oggetti, sovrascrivere significa sovrascrivere la funzionalità di un metodo esistente.
Esempio
Vediamo un esempio.
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // runs the method in Animal class
b.move(); // runs the method in Dog class
}
}
Questo produrrà il seguente risultato:
Produzione
Animals can move
Dogs can walk and run
Nell'esempio sopra, puoi vederlo anche se bè un tipo di animale che esegue il metodo di spostamento nella classe Dog. Il motivo è: in fase di compilazione, il controllo viene effettuato sul tipo di riferimento. Tuttavia, durante il runtime, JVM individua il tipo di oggetto ed eseguirà il metodo che appartiene a quel particolare oggetto.
Pertanto, nell'esempio precedente, il programma verrà compilato correttamente poiché la classe Animal ha il metodo move. Quindi, in fase di esecuzione, esegue il metodo specifico per quell'oggetto.
Considera il seguente esempio:
Esempio
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
public void bark() {
System.out.println("Dogs can bark");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // runs the method in Animal class
b.move(); // runs the method in Dog class
b.bark();
}
}
Questo produrrà il seguente risultato:
Produzione
TestDog.java:26: error: cannot find symbol
b.bark();
^
symbol: method bark()
location: variable b of type Animal
1 error
Questo programma genererà un errore in fase di compilazione poiché il tipo di riferimento di b Animal non ha un metodo con il nome di bark.
Regole per l'override del metodo
La lista degli argomenti dovrebbe essere esattamente la stessa di quella del metodo sovrascritto.
Il tipo restituito dovrebbe essere lo stesso o un sottotipo del tipo restituito dichiarato nel metodo originale sostituito nella superclasse.
Il livello di accesso non può essere più restrittivo del livello di accesso del metodo sostituito. Ad esempio: se il metodo della superclasse è dichiarato pubblico, il metodo sovrascritto nella sottoclasse non può essere privato o protetto.
I metodi di istanza possono essere sovrascritti solo se ereditati dalla sottoclasse.
Un metodo dichiarato final non può essere sovrascritto.
Un metodo dichiarato statico non può essere sovrascritto ma può essere nuovamente dichiarato.
Se un metodo non può essere ereditato, non può essere sovrascritto.
Una sottoclasse all'interno dello stesso pacchetto della superclasse dell'istanza può sovrascrivere qualsiasi metodo della superclasse non dichiarato privato o finale.
Una sottoclasse in un pacchetto diverso può solo sovrascrivere i metodi non finali dichiarati pubblici o protetti.
Un metodo override può generare eccezioni deselezionate, indipendentemente dal fatto che il metodo sottoposto a override generi eccezioni o meno. Tuttavia, il metodo sovrascritto non deve generare eccezioni verificate nuove o più ampie di quelle dichiarate dal metodo sostituito. Il metodo override può generare eccezioni più strette o meno rispetto al metodo sottoposto a override.
I costruttori non possono essere sovrascritti.
Utilizzando la parola chiave super
Quando si richiama una versione superclasse di un metodo sovrascritto, il file super viene utilizzata la parola chiave.
Esempio
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
super.move(); // invokes the super class method
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal b = new Dog(); // Animal reference but Dog object
b.move(); // runs the method in Dog class
}
}
Questo produrrà il seguente risultato:
Produzione
Animals can move
Dogs can walk and run