CIAO! Usi già i metodi Java e ne sai molto. Come funziona l'override del metodo - 1Sicuramente ti sei imbattuto in una classe con molti metodi che hanno lo stesso nome ma elenchi di argomenti diversi. Ricorderete che in quei casi abbiamo utilizzato l'overloading del metodo. Oggi daremo uno sguardo a una situazione diversa. Immagina di avere un metodo comune, ma dovrebbe fare cose diverse a seconda della classe in cui viene chiamato. Come implementiamo questo comportamento? Per capirlo, prendiamo la Animalclasse genitore, che rappresenta gli animali, e creiamo un speakmetodo in essa:

public class Animal {
  
   public void speak() {

       System.out.println("Hello!");
   }
}
Sebbene abbiamo appena iniziato a scrivere il nostro programma, probabilmente puoi vedere un potenziale problema: il mondo è pieno di molti animali, e tutti "parlano" in modo diverso: i gatti miagolano, le anatre cigolano, i serpenti sibilano, ecc. Il nostro obiettivo è semplice: Come funziona l'override del metodo - 2noi voglio evitare di creare una serie di metodi per parlare. Invece di creare un meow()metodo per miagolare, hiss()per sibilare, ecc., vogliamo che il serpente sibili, il gatto miagoli e il cane abbai quando speak()viene chiamato il metodo. Possiamo facilmente ottenere questo risultato usando l'override del metodo . Wikipedia spiega il termine come segue: Override del metodo, nella programmazione orientata agli oggetti, è una funzionalità del linguaggio che consente a una sottoclasse o classe figlio di fornire un'implementazione specifica di un metodo che è già fornito da una delle sue superclassi o classi padre. Questo è fondamentalmente corretto. L'override ti consente di prendere un metodo di una classe genitore e scrivere la tua implementazione in ogni classe derivata. La nuova implementazione nella classe figlia "sostituisce" quella nella classe genitore. Vediamo come appare con un esempio. Creiamo 4 discendenti della nostra Animalclasse:

public class Bear extends Animal {
   @Override
   public void speak() {
       System.out.println("Growl!");
   }
}
public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void speak() {
       System.out.println("Woof!");
   }
}


public class Snake extends Animal {

   @Override
   public void speak() {
       System.out.println("Hiss!");
   }
}
Ecco un piccolo trucco per il futuro: per eseguire l'override dei metodi di una classe genitore, vai nel codice della classe derivata in IntelliJ IDE , premi Ctrl+O e seleziona Override methods... dal menu. Abituati a usare i tasti di scelta rapida fin dall'inizio. Accelereranno la codifica! Per ottenere il comportamento desiderato, abbiamo fatto alcune cose:
  1. In ogni classe discendente, abbiamo creato un metodo con lo stesso nome del metodo nella classe genitore.
  2. Abbiamo detto al compilatore che non stiamo solo dando al metodo lo stesso nome della classe genitore, ma piuttosto vogliamo sovrascriverne il comportamento. Questo "messaggio" al compilatore viene trasmesso tramite l' annotazione @Override .
    L'annotazione @Override sopra un metodo dice al compilatore (così come ad altri programmatori che leggono il tuo codice), "Non preoccuparti. Questo non è un errore o una svista. Sono consapevole che questo metodo esiste già e voglio sovrascriverlo .

  3. Abbiamo scritto l'implementazione di cui abbiamo bisogno per ogni classe discendente. Quando speak()viene chiamato il metodo, un serpente dovrebbe sibilare, un orso dovrebbe ringhiare e così via.
Vediamo come funziona in un programma:

public class Main {

   public static void main(String[] args) {

       Animal animal1 = new Dog();
       Animal animal2 = new Cat();
       Animal animal3 = new Bear();
       Animal animal4 = new Snake();
      
       animal1.speak();
       animal2.speak();
       animal3.speak();
       animal4.speak();
   }
}
Uscita della console:

Woof! 
Meow! 
Growl! 
Hiss!
Ottimo, tutto funziona come dovrebbe! Abbiamo creato 4 variabili di riferimento il cui tipo è la Animalclasse genitore e assegnato loro 4 diversi oggetti delle classi discendenti. Di conseguenza, ogni oggetto si comporta in modo diverso. Per ciascuna delle classi derivate, il speak()metodo sovrascritto sostituisce il speak()metodo esistente della Animalclasse (che visualizza semplicemente "Speaking: " sulla console). Come funziona l'override del metodo - 3L'override del metodo ha diverse limitazioni:
  1. Un metodo sottoposto a override deve avere gli stessi argomenti del metodo nella classe padre.

    Se il speakmetodo della classe genitore accetta a Stringcome input, anche il metodo sovrascritto nella classe discendente deve accettare a Stringcome input. In caso contrario, il compilatore genererà un errore:

    
    public class Animal {
    
       public void speak(String s) {
    
           System.out.println("Speaking: " + s);
       }
    }
    
    public class Cat extends Animal {
    
       @Override // Error!
       public void speak() {
           System.out.println("Meow!");
       }
    }
    

  2. Il metodo sottoposto a override deve avere lo stesso tipo restituito del metodo nella classe padre.

    Altrimenti, otterremo un errore di compilazione:

    
    public class Animal {
    
       public void speak() {
    
           System.out.println("Hello!");
       }
    }
    
    
    public class Cat extends Animal {
    
       @Override
       public String speak() {         // Error!
           System.out.println("Meow!");
           return "Meow!";
       }
    }
    

  3. Anche il modificatore di accesso del metodo sottoposto a override non può differire da quello originale:

    
    public class Animal {
    
       public void speak() {
    
           System.out.println("Hello!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void speak() {      // Error!
           System.out.println("Meow!");
       }
    }
    
In Java, l'override del metodo è un modo per implementare il polimorfismo. Ciò significa che il suo principale vantaggio è quella flessibilità di cui abbiamo parlato prima. Possiamo costruire una gerarchia di classi semplice e logica, ognuna con un comportamento specifico (cani che abbaiano, gatti che miagolano) ma un'unica interfaccia: un unico metodo speak()per tutti piuttosto che una serie di metodi diversi, ad esempio bark(), meow(), ecc.