CIAO! Nelle lezioni precedenti, abbiamo già brevemente familiarizzato con il concetto di eredità. Oggi toccheremo di nuovo questo argomento, ma ancora una volta non troppo in profondità. Avremo ancora una lezione più dettagliata su questo in futuro. Oggi daremo solo una rapida occhiata ad alcuni esempi pratici e faremo conoscenza con un interessante operatore in Java.
Eredità
Quindi, cos'è l'eredità? L'ereditarietà è un meccanismo di programmazione (incluso in Java) che consente di dichiarare una nuova classe basata su una esistente. La classe derivata ottiene quindi l'accesso ai campi e ai metodi della classe padre. Perché ne avremmo bisogno? Bene, immagina di dover creare diverse classi di auto in un programma: Truck, RaceCar, Sedan, Pickup, ecc. Anche prima di scrivere qualsiasi codice, sai per certo che tutte queste classi hanno molto in comune: tutte le auto hanno un modello nome, anno di costruzione, cilindrata, velocità massima, ecc. (per non parlare del fatto che hanno tutte ruote e altre parti in comune). In questa situazione, puoi:- Crea questi campi in ogni classe (aggiungendoli a ogni nuova classe di auto mentre la crei)
- Porta i campi comuni a tutte le auto in una
Car
classe genitore, quindi usa la parola chiave extends per derivare tutte le classi per tipi specifici di auto dallaCar
classe.
public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
Come minimo, evitiamo l'inutile duplicazione del codice (e dovremmo sempre sforzarci di farlo quando scriviamo i programmi). Inoltre, abbiamo una struttura di classe semplice e comprensibile, con tutti i campi comuni a tutte le auto consolidati in un'unica classe. Se i camion hanno campi speciali che le altre auto non hanno, possono essere dichiarati nella Truck
classe. Lo stesso vale per i metodi. Tutte le auto hanno un certo comportamento comune che può essere descritto con metodi, ad esempio avviare l'auto, accelerare/frenare, ecc. Questi metodi comuni possono essere consolidati nella Car
classe genitore e ogni tipo specifico di auto può definire le sue azioni uniche nelle classi derivate .
public class Car {
public void gas() {
// Accelerate
}
public void brake() {
// Brake
}
}
public class F1Car extends Car {
public void pitStop() {
// Only race cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
Abbiamo aggiunto alla Car
classe i metodi comuni a tutte le auto. Ma guarda la F1Car
classe, che rappresenta le auto da corsa di "Formula 1". I pit stop (soste per manutenzione urgente dell'auto) vengono effettuati solo durante le gare, quindi abbiamo aggiunto questa funzionalità specifica alla relativa classe derivata.
operatore instanceof
In Java esiste un operatore speciale, instanceof , per verificare se un oggetto è stato creato sulla base di una particolare classe. Restituisce vero o falso a seconda del risultato del controllo. Vediamo come funziona usando le classi nel nostro esempio di auto:
public class Truck extends Car {
public static void main(String[] args) {
Truck truck = new Truck();
System.out.println(truck instanceof Car);
}
}
Output: true L' instanceof
operatore restituisce true , poiché abbiamo un Truck
oggetto e tutti i camion sono automobili. La Truck
classe è derivata dalla Car
classe. Tutti i camion vengono creati in base al genitore comune, la Car
classe. Osserva attentamente come instanceof
viene utilizzato l'operatore. Lo scrivi senza punto, poiché è un operatore, non un metodo ("object instanceof Class"). Proviamo in un altro modo:
public static void main(String[] args) {
Car car = new Car();
System.out.println(car instanceof Truck);
}
Output: false La Car
classe (e gli oggetti auto) non derivano dalla Truck
classe. Tutti i camion sono automobili, ma non tutte le automobili sono camion. Car
gli oggetti non sono basati sulla Truck
classe. Un altro esempio:
public static void main(String[] args) {
Car car = new Car();
Truck truck = new Truck();
System.out.println(car instanceof Object && truck instanceof Object);
}
Output: True Anche qui la logica è semplice: tutte le classi in Java, incluse le classi che crei, discendono dalla Object
classe (anche se non scrivi "extends Object"—è già implicito). Come e quando sarebbe utile? L' instanceof
operatore è più comunemente usato quando si esegue l'override del equals()
metodo. Ad esempio, ecco come il equals
metodo viene implementato nella String
classe:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
Prima di confrontare a String
con l'oggetto passato, il metodo verifica se l'oggetto è anche una stringa? Solo allora inizia a confrontare le proprietà dei due oggetti. Se questo test non esistesse, qualsiasi oggetto con campi valore e lunghezza potrebbe essere passato al metodo e confrontato con una stringa, il che sarebbe sbagliato, ovviamente.
GO TO FULL VERSION