Ereditarietà
Le classi possono essere derivate da altre classi, in modo da ereditare campi e metodi. Una classe che deriva da un’altra è chiamata sottoclasse o classe figlia, la classe da cui è derivata la sottoclasse è chiamata super classe o classe madre. Ad esclusione della classe Object, che non ha super classi ogni classe può avere una ed una sola super classe.
In assenza di una qualsiasi super classe, ogni classe p implicitamente una sottoclasse della classe Object. Per ereditare una classe si utilizza la parola chiave extends
public class Automobile { // variabili
public int cilindrata;
public int velocita; // costruttore
public Automobile(int cil, int vel){ cilindrata = cil;
velocita = vel;
}
public void setCilindrata(int c) {
cilindrata = c; }
public void setVelocita(int v) { velocita = v;
}
public void frena(int f) { velocita -= decrement;
}
public void accelera(int a) { velocita += a;
}
}
Ora definiamo una sottoclasse della classe Automobile:
public class Utilitaria extends Automobile {
//variabili
public int numeroPorte;
//costruttore
public Utilitaria(int nPorte, int cil,int vel,) { super(cil, vel); numeroPorte = nPorte;
}
//metodi
public void setNumeroPorte(int nPorte) {
numeroPorte = nPorte; }
}
La sottoclasse Utilitaria eredita tutti i campi e metodi di Automobile e aggiunge il campo numeroPorte e un metodo setNumeroPorte, come possiamo notare il concetto di ereditarietà è molto importante poiché ci consente di risparmiare molto codice!!!
Metodi di istanza nelle sottoclassi e Metodi di classe
Un metodo di istanaza in una sottoclasse che ha la stessa firma e restituisce lo stesso tipo come il metodo di istanza nella super classe , sostituisce il metodo della super classe.
Se una sottoclasse e finisce un metodo di classe con la stessa firma del metodo di classe della superclasse, il metodo della sottoclasse si dice che nasconde quello della superclasse.La distinzione tra hiding (nascondere) e overriding (sovrascrivere) ha importanti implicazioni. La versione del metodo sovrascritto che viene invocata è quella della sottoclasse.La versione del metodo nascosto che viene invocato dipende dal fatto se esso viene invocato dalla superclasse o della sottoclasse.Vediamo un esempio che contiene due classi. La prima è Animale, che contiene un metodo di istanza e un metodo di classe:
public class Animale {
public static void metodoDiClasse() {
System.out.println(“Metodo di classe in Animale.”);
}
public void metodoDiIstanza() {
System.out.println(“Metodo di istanza in Animale.”);
}
}
La seconda classe, è una sottoclasse di Animale, chiamata Gatto:
public class Cat extends Animale {
public static void metodoDiClasse() {
System.out.println(“Metodo di classe in Gatto.”);
}
public void metodoDiIstanza()
{ System.out.println(“Metodo di istanza in Gatto.”);
}
public static void main(String[] args) {
Gatto mioGatto = new Gatto (); Animale mioAnimale = mioGatto;
Animale. metodoDiClasse(); mioAnimale.metodoDiIstanza();
}
}
La classe Gatto esegue l’override del metodo di istanza in Animale e nasconde il metodo di classe in Animale. Il metodo main di questa classe crea un’istanza di Gatto e chiamametodoDiClasse()sulla classe e metodoDiIstanza() sull’istanza.
Poliformismo
Il termine polimorfismo si riferisce ad un qualcosa che può avere molte forme differenti. Questo principio può essere applicato anche alla programmazione orientata agli oggetti Il polimorfismo può essere dimostrato apportando una piccola modifica alla classe Automobile.
Ad esempio, si potrebbe aggiungere un metodo stampaDescrizioneche visualizza tutti i dati di questa classe (cilindrata e velocità):
public void stampaDescrizione(){
System.out.println(“l’auto ha “+ “una cilindrata pari a ” + this.cilindrata + “e viaggia ad una velocità pari a ”
+ this.velocita +”. “);
}
Per dimostrare le caratteristiche del polimorfismo nel linguaggioJava,estendiamo la classeAutomobile con la classe Utilitaria e una classe Spider.
Nella classe Utilitaria si aggiunge un campo numeroPorte.
public class Utilitaria extends Automobile{
private int numeroPorte;
public Utilitaria(int cil,int vel,int nPorte){ super(cil,vel); this.setNumeroPorte(nPorte);
}
public String getNumeroPorte(){
return this.numeroPorte; }
public void setNumeroPorte (int nPorte){ this.numeroPorte = nPorte;
}
public void stampaDescrizione(){ super.stampaDescrizione();
System.out.println(“l’utilitaria ha ” + getNumeroPorte() +
” porte.”);
}
}
Adesso, creiamola classeSpider
public class Spider extends Automobile{
private int numeroPosti;
public Spider(int cil,int vel, int nPosti){
super(cil, vel, nPosti);
this.setNumeroPosti(nPosti);
}
public int getNumeroPosti(){
return this.numeroPosti; }
public void setTireWidth(int nPosti){ this. numeroPosti = nPosti;
}
public void printDescription(){ super.stampaDescrizione(); System.out.println(“la spider ha”
+ getNumeroPosti() +
” posti.”);
}
}
Riassumendo, ci sono tre classi: Automobile, Utilitaria e Spider. Nelle due sottoclassi il metodo stampaDescrizione subisce l’override e stampa le informazioni univoche.
Non rimane che creare un programma di test che crea tre variabiliAutomobile.A ciascunavariabileè assegnata ad una delle tre classi. Ogni variabile viene poi stampata.
public class TestAutomobile {
public static void main(String[] args){
// creo tre oggetti di tipo Automobile Automobile auto1, auto2, auto3;
auto1= new Bicycle(1600, 100); auto2= new Utilitaria(1200, 80, 4); auto3= new Spider(2000, 120, 2);
auto1.printDescription(); auto2.printDescription(); auto3.printDescription();
}}
La parola chiave super
un campo che ha lo stesso nome diun campo della superclasse nasconde il campo di quest’ultima All’interno della sottoclasse, non è possibile fare riferimento al campo della superclasse richiamandolo semplicemente con il suo nome. Questo campo è accessibile attraverso il comando super.Se un metodo esegue l’override di uno dei metodi della superclasse, è possibile richiamare il metodo sovrascritto (dalla superclasse) attraverso l’uso della parola chiave super.
La superclasse Object
Ogni classe è figlia, diretta o indiretta, della classe Object.Ogni classeutilizzatao creataeredita imetodi di istanza di Object. I metodi ereditati da Object più utilizzati sono:
Il metodo equals()
Questo metodo confronta due oggetti e restituisce true se sono uguali.
Il metodo getClass()
Questo metodo restituisce un oggetto Class, il quale ha metodi che è possibileutilizzare per ottenereinformazioni sulla classe, comeil suo nome getSimpleName(), la sua superclasse getSuperclass(), e le interfacce che implementa getInterfaces().
Il metodo toString()
Il metodo toString() della classe Object restituisce la rappresentazione String di un oggetto, questo può essere molto utile per il debug.
Classi e metodi astratti
Una classe astratta è una classe che viene dichiarata astratta e può includere metodi astratti. Le classi astratte non possono essere istanziate, ma possono essere delle sottoclassi.Un metodo astratto è un metodo che viene dichiarato senza una implementazione (senza corpo), ad esempio:
abstract void muovi(double deltaX, double deltaY);
Se una classe contiene metodi astratti, la stessa classe deve essere dichiarata astratta, come:
public abstract class OggettoGrafico {
// dichiarazione dei campi
// dichiarazione di un metodo astratto
abstract void disegna();
}
Quando una classe astratta ha una sottoclasse, questa di solito fornisce le implementazioni per tutti i metodi astratti della superclasse astratta. Se ciò non accadesse la sottoclasse deve essere dichiarata abstract.
Interfacce
Nel linguaggio di programmazione Java, l’interfaccia è un oggetto, simile ad una classe, che può contenere solo costanti e firme dei metodi (metodi astratti).Non ci sono corpi dei metodi.Le interfacce non possono essere istanziate, queste possono essere solo implementate da classi o estese da altre interfacce.
public interface MyInterface {
// dichiarazione delle costanti
double E = 2.718282;
// metodi
void faiQualcosa1(int i, double x);
int faiQualcosa2(String s);
}
Se non si specifica che l’interfaccia è public questa è accessibile solamente alle classi definite nello stesso package dell’interfaccia in questione.
Un’interfaccia può estendere altre interfacce, così come una classe può estendere un’altra classe. Tuttavia, mentre una classe può estendere una sola altra classe, un’interfaccia può estendere un numero qualsiasi di interfacce.
public interface MyInterface extends Interface1, Interface2, Interface3{
}
Per dichiarare una classe che implementa un’interfaccia, è necessario includere la clausola implements nella dichiarazione della classe.
Una classe può implementare più di un’interfaccia, quindi la parola chiave implements è seguita da un elenco separato da virgole delle interfacce implementate dalla classe.