Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
Utilizzando il metodo costruttore sarà possibile allocare le due variabili una sola volta e i vari metodi chiamati leggeranno semplicemente il contenuto delle variabili d'istanza senza costruirne una copia. Vediamo dunque il codice di esempio:
public class OperazioniSuNumeri {
//campi
//variabili di ISTANZA
public numeroX;
public numeroY;
public OperazioniSuNumeri(int x, int y) { //costruttore
numeroX=x;
numeroY=y;
}
public int sottrazione() {
int sottrazione;
sottrazione=numeroX-numeroY;
return sottrazione;
}
public int somma() {
int somma;
somma=numeroX+numeroY;
return somma;
}
// gli altri metodi con la stessa struttura
}
E il codice per istanziare l'oggetto e la chiamata dei metodi sarà:
public class Implementazione {
public static void Main(String args[]) {
//Istanza della classe OperazionisuNumeri
OperazioniSuNumeri operazioni;
operazioni = new OperazioniSuNumeri(10,2);
int sottrazione = operazioni.sottrazione(); //richiamo il metodo sottrazione
int somma = operazioni.somma(); //richiamo il metodo somma
}
}
il metodo somma
//stampo a video i risultati ottenuti
System.out.println(somma);
System.out.println(sottrazione);
La prima parola chiave nei costruttori è this:
- Riferimento all'oggetto corrente;
- Non si può usare in metodi static;
- Normalmente è implicito.
La seconda parola chiave nei costruttori è super:
Il costruttore di una qualunque classe, come prima istruzione richiama il costruttore della superclasse a cui fa riferimento. Per esempio se istanziamo un oggetto di tipo "ResponsabileDiProgetto", il costruttore chiamerà automaticamente il costruttore della superclasse relativa, ovvero chiamerà il costruttore della classe "Dipendente" (se non è presente nessun costruttore viene richiamo il costruttore di default).
Sottolineiamo che la chiamata al costruttore della superclasse, in java, è una cosa inevitabile. Vediamo però come può essere gestita questa apparente limitazione utilizzando il
reference super(). Con il reference super è possibile accedere ad attributi o metodi della superclasse che abbiamo ereditato e quindi anche al costruttore della superclasse.
Es.
public class Dipendente {
private String nome;
private String cognome;
private int oreLavorativeMensili;
private int retribuzioneOraria;
public Dipendente(String n, String c, int o, int r) {
nome=n;
cognome=g;
oreLavorativeMensili=o;
retribuzioneOraria=r;
}
}
A questo punto, sfruttando il reference super() la classe "ResponsabileDiProgetto" sarà dunque la seguente:
public class ResponsabileDiProgetto {
int bonus;
public ResponsabileDiProgetto(String n, String c, int o, int r, int b) {
super(n,c,o,r);
bonus=b;
}
}
In questo modo nel caso in cui dovessimo modificare il costruttore della classe "Dipendente", magari mettendo alcune limitazioni sulle ore lavorative mensili, alla classe "ResponsabileDiProgetto" non dovremo apportare nessuna modifica, dato che con la chiamata a super() richiameremo il costruttore.
modificato, della superclasse "Dipendente". Inoltre il refernce super() ci ha permesso di evitare di ricopiare il codice presente nel costruttore della classe dipendente per l'assegnazione degli attributi nome, cognome ecc. Senza super() se immaginiamo di avere n classi ereditate da una superclasse ed ad un certo punto dover modificare il codice per i costruttori dovremo andare a mettere le mani su n classi differenti aumentando in maniera esponenziale la possibilità di commettere errori e creare bugs difficilmente rilevabili.
Modificatori di accesso (information hiding)
- Si applicano a metodi e campi;
- Specificano chi può accedere e sono 4 (ordinamento dal più al meno restrittivo):
- private: (non visibili all'esterno) accesso solo dal contesto di un metodo della stessa classe;
- protected: accesso solo dallo stesso package;
- public: accesso libero (per tutti);
Modificatore final.
- Il valore di default non viene assegnato;
- il campopuò essere inizializzato una sola volta (tipicamente dacostruttori);
rende le variabili di un metodo non modificabili;
nei campi di istanza rende gli oggetti immutabili;
una classe con tutti i campi di istanza final può essere istanziata creando oggetti immutabili;
nei metodi di istanza rende il metodo non sovrascrivibile in overriding.
Può essere utilizzato come campo di istanza di una classe.
La classe String oggetti immutabili.
La classe ArrayList
- versione dinamica dei classici array;
- libreria classe del java.
La gerarchia delle classi in Java
In java tutte le classi estendono direttamente o indirettamente e implicitamente o esplicitamente la classe Object (classe superiore a tutte), quindi tutte le volte che creiamo una classe senza ereditarietà è come se ereditassimo la classe Object che il Java ci mette a disposizione.
Es.
Class A extends Object {…}
Ogni variabile di tipo statico riferimento ha in realtà 2 tipi:
tipo statico: quello della dichiarazione, noto al compilatore;
tipo dinamico (perché può variare) es. tipo dinamico di b2 → B
tipo dinamico A a3 → null (non c'è)
Il polimorfismo: overloading e overriding
La parola polimorfismo indica la possibilità per uno stesso oggetto di assumere più forme; quindi l'attitudine di un oggetto a mostrare più implementazioni per una singola funzionalità.
In altre parole, potremmo dire che il polimorfismo consente ad oggetti differenti (ma collegati tra loro) la flessibilità di rispondere in modo diverso allo stesso tipo di messaggio.
Per chiarire il concetto possiamo fare un semplice esempio di applicazione del polimorfismo nella vita reale: quando facciamo riferimento ad un computer probabilmente useremo lo stesso termine (computer, appunto) sia per identificare un computer desktop, un portatile o un netbook. Questo tipo di generalizzazione viene effettuata in quanto gli
oggetti cui abbiamo fatto riferimento sostanzialmente effettuano le stesse operazioni...ma queste operazioni vengono fatte da oggetti con forme diverse (polimorfismo).
Polimorfismo dei metodi:
Dal punto di vista implementativo il polimorfismo per i metodi si ottiene utilizzando l'overload e l'override dei metodi stessi.
Un metodo è univocamente determinato se prendiamo in considerazione sia il suo nome che la lista di tutti i suoi parametri. Ciò permette, di fatto, di avere all'interno di una classe più metodi che hanno lo stesso nome, ma con parametri diversi.
L'overload quindi si basa sulla scrittura di più metodi identificati dallo stesso nome che però hanno, in ingresso, parametri di tipo e numero diverso.
Es.
public class OperazioniSuNumeri {
public int somma(int x, int y) {
return x+y;
}
public float somma(float x, float y) {
return x-y;
}
}
Dal punto di vista implementativo dunque non ci dovremo assolutamente preoccupare di effettuare controlli
public class Implementazione {
OperazioniSuNumeri numeri = new OperazioniSuNumeri();
sommaInteri = numeri.somma(3,4);
System.out.println("La somma tra interi è:");
System.out.println(sommaInteri);
sommaFloat = numeri.somma(2.1,8.3);
System.out.println("La somma tra float è:");
System.out.println(sommaFloat);
}
Il codice sopra scritto funzionerà perfettamente in quanto ogni volta che viene invocato il metodo somma, verranno controllati il tipo di parametro che gli sono stati passati ed in base a questa scelta, automaticamente, verrà richiamato il metodo appropriato.
System.out.println() è un metodo polimorfo.
Con il termine override si intende una vera e propria riscrittura di un certo metodo di una classe che abbiamo ereditato (tutto uguale in classi diverse).
Dunque, necessariamente, l'override implica ereditarietà.
Es.
public class Dipendente{
private String nome;
private String cognome;
private int oreLavorativeMensili;
private int retribuzioneOraria;
public int getOreLavorativeMensili(){
return oreLavorativeMensili;
}
public int getRetribuzioneOraria(){
return retribuzioneOraria;
}
public int stipendio(){
return oreLavorativeMensili * retribuzioneOraria;
}
}
Adesso ereditiamo la classe, creandone un'altra che modella il "ResponsabileDiProgetto" che, oltre ad uno stipendio fisso, ha un attributo che rappresenta un bonus di produzione. Dunque la retribuzione di questo dipendente sarà data dalla somma dello stipendio base con l'eventuale bonus. Quindi il codice per la classe sarà il seguente:
public class ResponsabileDiProgetto extends Dipendente {
private int bonus;
public int stipendio(){
int stipendioBase = (getOreLavorativeMensili() * getRetribuzioneOraria());
return stipendioBase + bonus;
}
}
Con l'override, quindi,È possibile ridefinire un metodo di una classe più generalista adattandolo così alla classe più specialista mantenendo comunque una coerenza per quanto riguarda la semantica del metodo che avrà lo stesso identico nome.
L'overload di un costruttore è possibile? Si, ed è un metodo molto potente che ci permette di costruire oggetti di una stessa classe che risulteranno però diversi.
L'override di un costruttore è possibile? Non è una tecnica utilizzabile in quanto quando estendiamo una classe i costruttori presenti in una classe non vengono ereditati, dunque non è possibile effettuare una riscrittura del costruttore.
Generics e modificatori di accesso
Idea: permette che i tipi siano come dei parametri per classi e metodi. In altre parole si definisce un insieme di classi che dipendono in modo parametrico da uno o più tipi. I metodi parametrizzati possono essere anche in classi standard senza parametri di tipo.
Vantaggi:
riutilizzo del codice e controllo migliore dei tipi a tempo di compilazione (es. ArrayList). Metodo equals.- Si trova nella classe Object e ritorna un boolean;
- Deve essere sovrascritto ogni qualvolta sviluppiamo una classe i cui oggetti devono essere confrontati per uguaglianza;
- Ha un parametro di tipo Object;
- Se il parametro di tipo è