Quando una sottoclasse fornisce un'implementazione specifica per un metodo che è già definito nella sua classe genitore, si parla di overriding del metodo. Il metodo sottoposto a override nella sottoclasse deve avere gli stessi parametri nome e tipo restituito del metodo nella classe genitore.
Regole per la sostituzione del metodo
- I parametri del nome e il tipo restituito devono corrispondere al metodo principale.
- Java sceglie quale metodo eseguire in fase di esecuzione in base al tipo di oggetto effettivo e non solo al tipo di variabile di riferimento.
- I metodi statici non possono essere sovrascritti.
- IL @Sostituisci annotazione rileva errori come errori di battitura nei nomi dei metodi.
class Animal { void move(){ System.out.println( 'Animal is moving.'); } void eat(){ System.out.println( 'Animal is eating.'); } } class Dog extends Animal{ @Override void move(){ // move method from Base class is overriden in this // method System.out.println('Dog is running.'); } void bark(){ System.out.println('Dog is barking.'); } } public class Geeks { public static void main(String[] args) { Dog d = new Dog(); d.move(); d.eat(); d.bark(); } }
Produzione
Dog is running. Animal is eating. Dog is barking.
Spiegazione: La classe Animal definisce funzionalità di base come mossa() E mangiare() . La classe Cane eredita da Animale e sovrascrive il metodo move() per fornire un comportamento specifico Il cane sta correndo. Entrambe le classi possono accedere ai propri metodi. Quando si crea un oggetto Dog, la chiamata move() esegue il metodo sovrascritto.

Casi speciali di overriding
1. Chiamata al metodo genitore utilizzando super
IL parola chiave eccellente può richiamare il metodo della classe genitore dal metodo sovrascritto.
Javaclass Parent{ void show(){ System.out.println('Parent's show()'); } } class Child extends Parent{ @Override void show(){ super.show(); System.out.println('Child's show()'); } } public class Main{ public static void main(String[] args){ Parent obj = new Child(); obj.show(); } }
Produzione
Parent's show() Child's show()
2. I metodi finali non possono essere sovrascritti
Se non vogliamo che un metodo venga sovrascritto lo dichiariamo come finale . Per favore vedi Utilizzo di Final con ereditarietà .
Javaclass Parent{ // Can't be overridden final void show(){ } } class Child extends Parent{ // This would produce error void show() {} }
Produzione :
3. Metodi statici
- I metodi statici non possono essere sovrascritti; la definizione di un metodo statico in una sottoclasse con la stessa firma della superclasse nasconde il metodo della superclasse.
- I metodi di istanza possono essere sovrascritti ma una sottoclasse non può sovrascrivere un metodo statico della superclasse.
- Un metodo statico in una sottoclasse con la stessa firma di un metodo statico della superclasse nasconde il metodo originale.
class Parent{ static void staticMethod(){ System.out.println('Parent static method'); } void instanceMethod(){ System.out.println('Parent instance method'); } } class Child extends Parent{ static void staticMethod(){ // Hides Parent's static method System.out.println('Child static method'); } @Override void instanceMethod(){ // Overrides Parent's instance method System.out.println('Child instance method'); } } public class GFG{ public static void main(String[] args){ Parent p = new Child(); // Calls Parent's static method (hiding) p.staticMethod(); // Calls Child's overridden instance method p.instanceMethod(); } }
Produzione
Parent static method Child instance method
4. Metodi privati
- I metodi privati non possono essere sovrascritti perché non sono visibili alle sottoclassi.
- Un metodo della sottoclasse con lo stesso nome viene trattato come un nuovo metodo indipendente non correlato alla classe genitore.
class Parent{ private void display(){ System.out.println('Parent private method'); } } class Child extends Parent{ void display(){ // This is a new method not overriding System.out.println('Child method'); } } public class GFG{ public static void main(String[] args){ Child c = new Child(); // Calls Child's method c.display(); } }
Produzione
Child method
5. Tipi di rendimento covariante
- Nell'override del metodo, il tipo restituito del metodo sottoposto a override può essere una sottoclasse del tipo restituito del metodo sottoposto a override.
- Questa funzionalità è nota come tipo restituito covariante e consente tipi restituiti più specifici nella sottoclasse.
class Parent{ Parent getObject(){ System.out.println('Parent object'); return new Parent(); } } class Child extends Parent{ @Override // Covariant return type Child getObject() { System.out.println('Child object'); return new Child(); } } public class GFG{ public static void main(String[] args){ Parent obj = new Child(); // Calls Child's method obj.getObject(); } }
Produzione
Child object
Gestione delle eccezioni nell'overriding
- Il metodo di override non può generare eccezioni controllate nuove o più ampie rispetto al metodo nella superclasse.
- Può generare eccezioni controllate in numero inferiore o più ristretto.
- Può lanciare qualsiasi eccezione non controllata (come RuntimeException) indipendentemente dal metodo della superclasse.
import java.io.IOException; class Parent { void display() throws IOException { System.out.println('Parent method'); } } class Child extends Parent { @Override void display() throws IOException { System.out.println('Child method'); } } public class GFG{ public static void main(String[] args){ // Parent reference Child object Parent obj = new Child(); try{ // Calls Child's overridden method obj.display(); } catch (IOException e){ System.out.println('Exception caught: ' + e.getMessage()); } } }
Produzione
Child method
Perché utilizziamo l'overriding del metodo?
- Per modificare o migliorare il comportamento di un metodo esistente in una sottoclasse.
- Per ottenere il polimorfismo di runtime, le chiamate ai metodi dipendono dal tipo di oggetto effettivo.
- Riutilizzare i nomi dei metodi riducendo logicamente la ridondanza.
Esempio di vita reale: sistema di gestione dei dipendenti
Comprendiamo l'override con un'analogia con il mondo reale.
Immagina il sistema di gestione dei dipendenti di un’organizzazione. Tutti i dipendenti condividono alcuni comportamenti come raiseSalary() e promo() ma la logica è diversa per ruoli diversi come Manager o Ingegnere. Possiamo creare un singolo array Employee in cui i singoli dipendenti sono di diversi tipi (tecnologia di vendita, ecc.) e chiamare le loro funzioni. Ciò semplifica molto il codice generale.
Javaabstract class Employee { abstract void raiseSalary(); abstract void promote(); } class Manager extends Employee{ @Override void raiseSalary(){ System.out.println( 'Manager salary raised with incentives.'); } @Override void promote(){ System.out.println( 'Manager promoted to Senior Manager.'); } } class Engineer extends Employee{ @Override void raiseSalary(){ System.out.println( 'Engineer salary raised with bonus.'); } @Override void promote(){ System.out.println( 'Engineer promoted to Senior Engineer.'); } } public class Company{ public static void main(String[] args){ Employee[] employees = { new Manager() new Engineer() }; System.out.println('--- Raising Salaries ---'); for (Employee e : employees){ e.raiseSalary(); } System.out.println('n--- Promotions ---'); for (Employee e : employees) { e.promote(); } } }
Produzione
--- Raising Salaries --- Manager salary raised with incentives. Engineer salary raised with bonus. --- Promotions --- Manager promoted to Senior Manager. Engineer promoted to Senior Engineer.
Spiegazione: Sebbene si faccia riferimento sia agli oggetti Manager che a quelli Engineer utilizzando il tipo Employee, Java chiama i metodi sovrascritti degli oggetti reali in fase di runtime dimostrando l'invio dinamico del metodo (polimorfismo di runtime).
Articolo correlato: Overloading e overriding del metodo