






Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Appunti del corso di ALGORITMI E PROGRAMMAZIONE del prof. Fabio Sartori. Overloading, costruttori
Tipologia: Appunti
1 / 10
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!







Immaginiamo di avere il metodo per calcolare l’area dei quadrilateri: ad ogni quadrilatero diverso corrisponde una formula diversa. Sono tutte delle figure che più o meno corrispondono a un’idea simile ma sono effettivamente forme diverse a cui corrispondono formule diverse. Potremmo ingegnarci per costruire un metodo generale che vada bene per tutti, ma ciò risulterebbe scomodo. → Sarebbe bello avere un modo per associare a ciascun quadrilatero la sua forma. Esempio : potremmo avere un metodo “area rombo” che sta nella classe rombo, un metodo per il trapezio nella classe trapezio… avrei tantissimi oggetti tutti scollegati tra loro. Quale sarebbe quindi la cosa ideale? Avere un unico progenitore quadrilatero che cerca una soluzione unica che vada bene per tutti a patto di costruire un metodo molto complicato che trascuri quelle che sono le formule specifiche, o tentare di seguirle, creando metodi specifici che però portano ad avere esplosione di contenuti (ogni metodo dovrà essere replicato sulla sua classe)? La cosa migliore sarebbe una via di mezzo. La prima soluzione di avere un metodo unico porterebbe ad avere una soluzione che non rispecchia pienamente la realtà del dominio che stiamo rappresentando: saremmo a posto da un punto di vista algoritmico, ma non dal punto di vista della modellazione (il nostro obiettivo quest’anno è modellare un dominio, cogliendone gli aspetti di rappresentazione e significato). D’altra parte non posso neanche pensare di avere una specializzazione stretta che non consideri il fatto che tutte le figure che ho vengono da un progenitore comune, perchè perderei delle proprietà fondamentali: rischierei di vedere tutte queste figure una slegata dall’alta, perdendo le relazioni che esistono tra di esse. Le relazioni che esistono tra le entità del dominio che rappresentiamo devono sempre essere considerate!!! Il modo migliore per affrontare un problema di questo tipo è avere la possibilità di definire un metodo generale che ci permetta di calcolare l’area di un quadrilatero generale, e avere poi la possibilità di ridefinire il metodo per ciascuna classe dei quadrilateri a seconda della figura e delle sue caratteristiche. Si parte quindi da un metodo comune, e una volta definita la figura particolare che si vuole considerare, si avrà la possibilità di capire quale sia il metodo specifico migliore da usare. Questo è il concetto di overloading , ossia ridefinizione di un metodo (all’interno della stessa classe di oggetti; poi lo vedremo anche all’interno di una gerarchia di classi differenti)
Fino ad ora abbiamo sempre prima creato un oggetto e poi dato valore agli attributi. Dal punto di vista formale però non è il procedimento corretto: abbiamo sempre un istante in cui l’oggetto rimane inconsistente con la realtà. Ad esempio se creiamo il nostro quadrilatero con i suoi 4 lati di tipo double, quelli rimarranno con i valori di default pari a 0.0 fino a che non gli assegniamo noi dei valori. C’è un modo per far sì che l’oggetto nasca già con i giusti valori degli attributi, conoscendoli, così da evitare questa inconsistenza tra creazione e chiamata dei metodi di incapsulamento? Il modo che abbiamo è l’utilizzo dei costruttori. In realtà li abbiamo già usati inconsciamente. Quando abbiamo costruito oggetti con l’istruzione new nomeClasse e poi le parentesi tonde, abbiamo invocato il costruttore di default, ed era questo il motivo per cui agli attributi venivano assegnati questi valori di default. Questo però non ci può bastare: se conosciamo già i valori con cui l'oggetto deve nascere, dobbiamo essere in grado di assegnarli all’oggetto già in fase di creazione. L’INIZIALIZZAZIONE DEGLI OGGETTI
public void setVelocita(int v) { if(v>=0 && v <= 180) { velocitaCorrente = v; } else { velocitaCorrente = 0; } } public void setProprietario(String p) { proprietario = p; } ... } public class TestAuto { public static void main(String ar[]) { //Voglio creare l’auto di Paperino con velocità 100 Automobile a = new Automobile(100, “Paperino”); } } Se mettessi controllo in costruttore e non in set, potrei costruire con il metodo set un'automobile con una velocità che non rispetta i vincoli. I controlli vanno messi nel metodo set perchè è quello che varia il valore. POSSO ANCORA USARE L’ISTANZIAZIONE CLASSICA? Considerando l’esempio precedente, la seguente istruzione è lecita? Automobile a = new Automobile(); NO! Perchè non esiste un costruttore nella classe Automobile che non accetta in ingresso parametri (chiamato costruttore di default)! Perché prima era lecita? E perché potevo istanziare oggetti?
Posso avere più costruttori all’interno di una classe, se ha senso. In genere ha senso se non ho tutti i parametri in ingresso: non sempre ho all’inizio tutte le informazioni per la costruzione dell’oggetto, soprattutto se i parametri sono molti. Posso così iniziare a inizializzare un certo set di parametri e dare valori di default agli altri, che verranno poi definiti con incapsulamento quando saranno disponibili.
Per fare ciò, non invoco esplicitamente il costruttore con il nome (avrei errore di ambiguità), ma utilizzo la keyword this (deve essere la prima istruzione nella definizione del metodo; spesso è anche l’unica). Non this. come se fosse variabile ma this() a mo’ di metodo. public class Automobile { private int velocitaCorrente; private String proprietario; public Automobile(int velocitaC, String proprietario) { setVelocitaCorrente(velocitaC); this.proprietario = proprietario; } public Automobile(String proprietario) { this(0, proprietario); } public Automobile(int velocita) { this(velocita, null); } public Automobile() { this(0, null); } ... } I costruttori eseguiranno l’inizializzazione mentre i metodi le operazioni. Con l’overloading sui metodi ho il rischio di cambiare i reference su cui sto lavorando: devo stare attenta a quale sia il metodo da richiamare all’interno dell’altro metodo. Conviene quindi partire dai metodi meno specifici, con un set di parametri meno esteso e richiamarli all’interno di quelli più estesi (contrario di quanto si fa con costruttori). Con i metodi è quindi necessario andare in senso inverso rispetto ai costruttori.