Ereditarietà in Java è uno dei concetti fondamentali della Programmazione Orientata agli Oggetti. L’ereditarietà in Java viene utilizzata quando abbiamo una relazione è-una tra gli oggetti. L’ereditarietà in Java è implementata utilizzando la parola chiave extends
.
Ereditarietà in Java
L’ereditarietà in Java è il metodo per creare una gerarchia tra le classi ereditando da altre classi.
L’ereditarietà in Java è transitiva – quindi se Sedan estende Car e Car estende Vehicle, allora Sedan viene ereditato anche dalla classe Vehicle. Il Vehicle diventa la superclasse sia di Car che di Sedan.
L’ereditarietà è ampiamente utilizzata nelle applicazioni Java, ad esempio estendendo la classe Exception per creare una classe Exception specifica dell’applicazione che contiene più informazioni come codici di errore. Ad esempio NullPointerException.
Esempio di Ereditarietà in Java
Ogni classe in Java estende implicitamente la classe java.lang.Object
. Quindi la classe Object è al livello superiore della gerarchia di ereditarietà in Java.
Vediamo come implementare l’ereditarietà in Java con un esempio semplice.
Superclasse: Animale
package com.journaldev.inheritance;
public class Animal {
private boolean vegetarian;
private String eats;
private int noOfLegs;
public Animal(){}
public Animal(boolean veg, String food, int legs){
this.vegetarian = veg;
this.eats = food;
this.noOfLegs = legs;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public String getEats() {
return eats;
}
public void setEats(String eats) {
this.eats = eats;
}
public int getNoOfLegs() {
return noOfLegs;
}
public void setNoOfLegs(int noOfLegs) {
this.noOfLegs = noOfLegs;
}
}
L’animale è la classe di base qui. Creiamo una classe Gatto che eredita dalla classe Animale.
Sottoclasse: Gatto
package com.journaldev.inheritance;
public class Cat extends Animal{
private String color;
public Cat(boolean veg, String food, int legs) {
super(veg, food, legs);
this.color="White";
}
public Cat(boolean veg, String food, int legs, String color){
super(veg, food, legs);
this.color=color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
Si noti che stiamo usando la parola chiave extends
per implementare l’ereditarietà in Java.
Programma di test di ereditarietà in Java
Scriviamo una semplice classe di test per creare un oggetto Gatto e utilizzare alcuni dei suoi metodi.
package com.journaldev.inheritance;
public class AnimalInheritanceTest {
public static void main(String[] args) {
Cat cat = new Cat(false, "milk", 4, "black");
System.out.println("Cat is Vegetarian?" + cat.isVegetarian());
System.out.println("Cat eats " + cat.getEats());
System.out.println("Cat has " + cat.getNoOfLegs() + " legs.");
System.out.println("Cat color is " + cat.getColor());
}
}
Output:
La classe Gatto non ha il metodo getEats()
ma il programma funziona comunque perché eredita dalla classe Animale.
Punti importanti
-
Il riutilizzo del codice è il beneficio più importante dell’ereditarietà perché le sottoclassi ereditano le variabili e i metodi della superclasse.
-
I membri privati della superclasse non sono direttamente accessibili alla sottoclasse. Come in questo esempio, la variabile noOfLegs di tipo Animale non è accessibile alla classe Gatto, ma può essere accessibile indirettamente tramite i metodi getter e setter.
-
I membri della superclasse con accesso predefinito sono accessibili alla sottoclasse SOLO se si trovano nello stesso pacchetto.
-
I costruttori della superclasse non sono ereditati dalla sottoclasse.
-
Se la superclasse non ha un costruttore predefinito, allora anche la sottoclasse deve avere un costruttore esplicito definito. Altrimenti verrà generata un’eccezione durante la compilazione. Nel costruttore della sottoclasse, la chiamata al costruttore della superclasse è obbligatoria in questo caso e dovrebbe essere la prima istruzione nel costruttore della sottoclasse.
-
Java non supporta l’ereditarietà multipla, una sottoclasse può estendere solo una classe. La classe Animal implicitamente estende la classe Object e la classe Cat estende la classe Animal, ma a causa della natura transitiva dell’ereditarietà in Java, la classe Cat estende anche la classe Object.
-
Possiamo creare un’istanza della sottoclasse e quindi assegnarla a una variabile della superclasse, questo è chiamato upcasting. Di seguito è riportato un semplice esempio di upcasting:
Gatto c = new Gatto(); //istanza della sottoclasse Animale a = c; //upcasting, è corretto poiché il Gatto è anche un Animale
-
Quando un’istanza di Superclasse viene assegnata a una variabile di Sottoclasse, allora si chiama downcasting. Dobbiamo eseguire un cast esplicito a Subclasse. Ad esempio;
Gatto c = new Gatto(); Animale a = c; Gatto c1 = (Gatto) a; //casting esplicito, funziona correttamente perché "c" è effettivamente di tipo Gatto
Nota che il compilatore non si lamenterà anche se stiamo facendo qualcosa di sbagliato, a causa del casting esplicito. Di seguito sono riportati alcuni casi in cui verrà lanciata un’
ClassCastException
a runtime.Cane d = new Cane(); Animale a = d; Gatto c1 = (Gatto) a; //ClassCastException a runtime Animale a1 = new Animale(); Gatto c2 = (Gatto) a1; //ClassCastException perché a1 è effettivamente di tipo Animale a runtime
-
Possiamo sovrascrivere il metodo della Superclasse nella Sottoclasse. Tuttavia, dovremmo sempre annotare il metodo sovrascritto con @Override. Il compilatore saprà che stiamo sovrascrivendo un metodo e, se qualcosa cambia nel metodo della superclasse, otterremo un errore di compilazione anziché ottenere risultati indesiderati a runtime.
-
Possiamo chiamare i metodi della superclasse e accedere alle variabili della superclasse utilizzando la parola chiave super. È utile quando abbiamo una variabile/metodo con lo stesso nome nella sottoclasse ma vogliamo accedere alla variabile/metodo della superclasse. Questo è anche utilizzato quando i costruttori sono definiti nella superclasse e nella sottoclasse e dobbiamo chiamare esplicitamente il costruttore della superclasse.
-
Possiamo usare l’istruzione
instanceof
per verificare l’ereditarietà tra gli oggetti, vediamo questo con l’esempio qui sotto.
```
Cat c = new Cat();
Dog d = new Dog();
Animal an = c;
boolean flag = c instanceof Cat; //normal case, returns true
flag = c instanceof Animal; // returns true since c is-an Animal too
flag = an instanceof Cat; //returns true because a is of type Cat at runtime
flag = an instanceof Dog; //returns false for obvious reasons.
```
- Non possiamo estendere classi Final in Java.
- Se non prevedi di utilizzare la Superclasse nel codice, ossia se la tua Superclasse è solo una base per mantenere del codice riutilizzabile, allora puoi mantenerla come classe astratta per evitare un’istanziazione non necessaria da parte delle classi client. Ciò limiterà anche la creazione di istanze della classe di base.
Video tutorial sull’ereditarietà in Java
I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.
Puoi consultare ulteriori esempi di ereditarietà nel nostro Repository GitHub.
Riferimento: Documentazione Oracle
Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example