PROGRAMMAZIONE A OGGETTI (OOP) Lezione 4 prj Mesa (Prof

annuncio pubblicitario
PROGRAMMAZIONE A OGGETTI (OOP) Lezione 4 prj Mesa (Prof. Ing N. Muto)
In questa lezione applicheremo tutti i concetti teorici fin qui esposti, sarà presentato codice
sviluppato in C# sviluppato con l'IDE (Integrated Development Environnemt) di Visual Studio
Express Edition 2008, liberamente scaricabile ed installabile.
Programmazione a oggetti in C#
Dopo aver affrontato i concetti di base e le caratteristiche portanti della OOP è ora arrivato il
momento di imparare concretamente come programmare ad oggetti con un linguaggio reale ed
in particolare il C#. Questo linguaggio è la “dote” che ha portato in casa Microsoft Anders
Hejlsberg l'inventore di “Delphi”, un linguaggio in Object Pascal che ha avuto un enorme successo.
La sintassi del C# prende spunto sia da quella di Delphi che di C++, di Java e di Visual
Basic per gli strumenti di programmazione visuale e per la sua semplicità. Il risultato è un linguaggio con meno simbolismo rispetto a C++, meno elementi decorativi rispetto a Java, ma comunque orientato agli oggetti in modo nativo.
Rispetto al C ed al C++, C# risulta più semplice e sicuro, in particolare possiamo elencare
le seguenti differenze:
• I puntatori possono essere utilizzati solo in particolari blocchi di codice marcati come
"unsafe".
• In molte operazioni aritmetiche vengono controllati eventuali "overflow".
• Gli oggetti dinamici non vengono deallocati esplicitamente; la loro rimozione viene
gestita automaticamente (implicitamente) dal "garbage-collector" quando non esistono
più riferimenti a tali oggetti. Questa gestione evita i due problemi ben noti dei dangling
pointer e del memory leak, anche se con un'ovvia riduzione delle prestazioni.
• Come in Java, è possibile ereditare da una sola classe (diversamente da quanto avviene
in C++) ma è possibile implementare un numero indefinito di interfacce.
• Le sole conversioni implicite consentite sono quelle "safe", ovvero che non espongono al
rischio di perdita di dati causata dalla diversa tipologia di dato. Ad esempio non sono
consentite conversioni implicite fra integer e boolean o fra enumerati ed integer.
• C# non possiede i "template" (tipici del C++) ma nella versione 2.0 sono stati introdotti i
"generic".
Rispetto a Java invece possiamo elencare questi punti:
Java utilizza i commenti Javadoc-sintax per generare la documentazione dal codice sorgente, mentre C# utilizza la sintassi XML nei commenti per lo stesso scopo.
• Quello che in Java è chiamato package, in C# viene chiamato namespace o "spazio di
nomi". Un ulteriore livello di organizzazione in C# è costituito dagli "assembly", che
possono contenere al proprio interno diversi spazi di nomi.
Dopo queste indicazioni tecniche specifiche per il cui approfondimento rimandiamo ai link
presenti in Internet, veniamo finalmente ad usare il C# per creare una classe.
Per prima cosa vediamo la “sintassi” ossia come si scrive o meglio “implementa” una classe:
public class retta {
}
//qui vanno aggiunte le proprietà e i metodi...
La classe precedente è quindi una classe “vuota”, serve solo a far vedere la forma; ora vediamo invece un esempio di classe completa:
//questa classe rappresenta l'entità “retta” espressa nella forma implicita ax + by +c = 0;
class retta {
// questa parte contiene la dichiarazione delle proprietà o attributi
public double a;
public double b;
public double c;
private double m;
//questo attributo è dichiarato private (privato) per nasconderlo al resto del codice
//qui di seguito è presente il costruttore della classe
public retta(double pa, double pb, double pc )
{
a= pa;
b= pb;
c= pc;
}
//questo metodo consente di calcolare il coefficiente angolare noti i coefficienti della retta in forma implicita
public double CalcolaM(){
if(a!=0) {
m=-b/a;
return m;
}
else {
Console.WriteLine("Impossibile eseguire il calcolo");
return 0;
}
}
}
Precisiamo alcune cose che abbiamo visto nel codice sopra riportato: la parola chiave
“private” detto anche modificatore di visibilità, rende gli attributi ed i metodi a cui è applicata
visibili e quindi utilizzabili
SOLO dai metodi della classe stessa. Se non si specifica alcun
modificatore, si presuppone che valga “private”.
Il metodo “public retta(double pa, double pb, double pc ) ”
è SPECIALE e si chiama
COSTRUTTORE della classe. Come si può notare ha lo stesso nome della classe, non
restituisce alcun valore ed è di tipo “public”. Il suo scopo è quello di “istanziare” la classe, ossia
creare l'oggetto reale a partire dalla “ricetta” definita nella classe. Proprio perché è un codice
che viene eseguito nel momento iniziale della “vita” di un oggetto, è adatto anche a contenere
delle istruzioni (azioni) che vanno compiute subito dopo la creazione dell'oggetto stesso, come
ad esempio caricare in alcune variabili dei valori iniziali. Infatti, se riguardiamo le istruzioni in
cui si creano gli attributi, notiamo che non viene specificato alcun valore iniziale.
Vediamo ora come si effettua l'istanza della classe, ossia si crea un oggetto realmente
esistente nella memoria centrale del calcolatore, a partire dalla sua ricetta, ossia dalla classe:
namespace RisolutoreSis1G
{
class Program
{
static void Main(string[] args)
{
Double A=0;
Double B=0;
Double C=0;
Double XSoluzione = 0;
Double YSoluzione = 0;
Console.WriteLine("* PROGRAMMA PER LA RISOLUZIONE DI SISTEMI DI DUE RETTE *");
Console.WriteLine("Inserisci a, b, c per la prima retta");
A=Convert.ToDouble(Console.ReadLine());
B=Convert.ToDouble(Console.ReadLine());
C=Convert.ToDouble(Console.ReadLine());
retta r1 = new retta(A,B,C);
//questa istruzione crea l'oggetto r1 a partire dalla classe “retta”
Console.WriteLine("Inserisci a, b, c per la seconda retta");
A = Convert.ToDouble(Console.ReadLine());
B = Convert.ToDouble(Console.ReadLine());
C = Convert.ToDouble(Console.ReadLine());
retta r2 = new retta(A, B, C);
//questa istruzione crea l'oggetto r2 sempre a partire dalla classe “retta”
//controllo che le rette non siano coincidenti
if((r1.a/r2.a==r1.b/r2.b)&&(r1.b/r2.b==r1.c/r2.c)) {
Console.WriteLine("Rette coincidenti: Infinite soluzion1!");
}
//controllo che le rette non siano parallele
else if (r1.CalcolaM() == r2.CalcolaM())
//questa istruzione usa il metodo CalcolaM
{
Console.WriteLine("Rette parallele: Nessuna soluzione!");
}
else {
//Eseguo il calcolo per trovare l'intersezione
YSoluzione = (((r2.a*r1.c)/r1.a)-r2.c)/(-r2.a*r1.b+r2.b);
XSoluzione = -r1.c / r1.a - r1.b / r1.a * YSoluzione;
Console.WriteLine("Le soluzioni sono X= {0} Y={1}", XSoluzione, YSoluzione);
}
Console.ReadLine();
}
}
Commentiamo le parti evidenziate in giallo che sono relative alla creazione dell'oggetto:
retta r1 = new retta(A,B,C);
r1: è il nome della variabile composta che stiamo per creare; si tratta dell'OGGETTO.
retta: è il nome della classe che stiamo usando per creare l'oggetto r1
new: è un operatore che, partendo dalla ricetta “retta” è in grado di creare l'oggetto r1.
Notare che new ha SEMPRE bisogno del costruttore e se avessimo creato una classe
senza un costruttore dichiarato esplicitamente, new avrebbe comunque usato un costruttore
creato implicitamente dal compilatore.
Una volta creato l'oggetto ci rimane da capire come si usa e per questo basta esaminare la
riga di codice evidenziata in verde e qui riportata:
else if (r1.CalcolaM() == r2.CalcolaM())
Ciò che notiamo è l'utilizzo del “.” ossia del carattere punto: r1.CalcolaM() è come dire, usa
l'oggetto r1 ed in particolare “accedi” al metodo CalcolaM()
Analogamente possiamo accedere al metodo CalcolaM() dell'altro oggetto retta r2.
Ovviamente questo è possibile perché il metodo CalcolaM() è dichiarato “public”!
Cosa accadrebbe infatti se provassimo a scrivere:
... if( r1.m == r2.m )...
Accadrebbe che il compilatore ci avviserebbe che m non è accessibile!
Come applicazione concreta di quanto fin qui spiegato si lasciano i seguenti esercizi da sviluppare con l'ambiente di sviluppo gratuito Visual Studio Express Edition 2008 o successivi, che
sono gratuiti e completi.
Esercizio 1:
Definire una classe per gestire un cellulare. Disegnare anche il modello UML. La classe deve comprendere almeno tre attributi di cui uno almeno private e contenere due metodi oltre al costruttore.
Esercizio 2:
Definire una classe per gestire il numero complesso nella forma: Z = a+jb. Disegnare anche il modello
UML. La classe deve contenere due metodi in grado di calcolare e restituire il modulo e l'argomento del
numero complesso.
Scarica