E' arrivato il momento di entrare nel vivo della programmazione C# descrivendo prima, ed usando poi, un concetto che è alla base di questo linguaggio (ed altri linguaggi moderni): le classi. All'inizio di questo corso, ho detto che il C# è un linguaggio orientato agli oggetti (O.O.P. = Object Oriented Programming). Un oggetto è la realizzazione in pratica di un qualcosa descritto in teoria. Esso ha delle caratteristiche, delle proprietà, degli attributi e dei metodi per utilizzarlo. Quando un architetto progetta una casa, ne fa il progetto su carta tramite un disegno che ne descrive le dimensioni, le caratteristiche ed eventualmente le tecniche di costruzione. Questo lavoro rappresenta la descrizione teorica di un oggetto (Casa) che dovrà essere costruito. In questo esempio, il progetto rappresenta la classe, mentre la casa realmente costruita, rappresenta l'oggetto vero e proprio. Usando la terminologia ad hoc, si dice che è stato istanziato l'oggetto casa cioè è stata creata una istanza della classe (progetto) Casa. In parole povere le classi sono definizioni usate per la creazione di oggetti. Dal progetto dell'architetto, volendo, si possono costruire più case. Per le classi, il concetto è lo stesso; da una classe si possono istanziare uno o più oggetti, dipende da quanti oggetti dello stesso tipo abbiamo bisogno in una applicazione. Facciamo un esempio: la classe Studente descrive tutte le caratteristiche di uno studente, per es. il nome, il cognome, la provenienza, ecc. . Con una istanza della classe Studente, che chiameremo Alunno, creeremo effettivamente un oggetto reale a partire della classe e che potremo usare nel nostro programma. E' ovvio che in una aula di una scuola c'è più di un alunno, quindi istanzieremo più classi Studente per formare la nostra aula di oggetti Alunno. Per saper utilizzare al meglio un linguaggio orientato agli oggetti, è necessario capire alcune caratteristiche molto importanti.
Non preoccupatevi se avete incontrato qualche difficoltà nell'apprendere questi concetti, è normale, man mano che andremo avanti si chiariranno. Definizione di una classe. Per definire una classe, abbiamo bisogno di una intestazione rappresentata dalla parola chiave class e da un corpo che ne racchiude il contenuto, così: class NomeClasse { elementi definiti nel corpo } dove il NomeClasse o identificatore rappresenta il nome che vogliamo dare alla classe. E’ utile dare un nome significativo alla classe che ne descriva l’impiego. Ad esempio possiamo definire la classe Studente: class Studente { elementi definiti nel corpo } dal suo identificatore (Studente), capiamo al volo che si tratta di qualcosa che a che fare con una persona; un altro esempio: class Autovettura { elementi definiti nel corpo } anche in questo caso si capisce, dall’identificatore (Autovettura), che avremo a che fare con un veicolo. Una volta creata una classe, non possiamo utilizzarla senza dichiararla. Siamo di fronte ad un tipo particolare di dato che noi abbiamo realizzato (progetto) e da questo dobbiamo creare un oggetto che lo rappresenti e che possiamo utilizzare. La dichiarazione (istanza) di una classe avviene in maniera quasi banale, cioè faremo così: NomeClasse nomeOggetto = new NomeClasse(); ritornando agli esempi che ho fatto prima, possiamo creare (istanziare) un oggetto Studente che chiameremo Alunno così: Studente Alunno = new Studente (); allo stesso modo per un oggetto Autovettura che chiameremo MiaMacchina: Autovettura MiaMacchina = new Autovettura (); abbiamo creato due oggetti, Alunno di tipo Studente e MiaMacchina di tipo Autovettura. Ma questi oggetti non servono a molto in una applicazione, sono oggetti "vuoti", cioè non contengono al loro interno qualcosa che li faccia distinguere tra loro. Per esempio un Alunno avrà pure un nome ed un cognome, la MiaMacchina avrà pure una cilindrata, una marca, un colore, ecc. . Ebbene, per avere queste informazioni, dobbiamo necessariamente inserire all’interno del loro corpo delle variabili che ci indicano tali informazioni, o per meglio dire, tali proprietà. Tali variabili vengono definite, in gergo tecnico, variabili istanza o campi istanza. Facciamo subito un esempio di come vengono dichiarati i campi istanza. Prendiamo la classe Studente che qui ripropongo: class Studente { elementi definiti nel corpo } senza ombra di dubbio possiamo affermare che uno studente ha un nome ed un cognome che potremmo rappresentare tramite due variabili di tipo stringa. Ecco come: class Studente { // definisco due campi istanza string nome; string cognome; } Ora la classe ha un aspetto più concreto ma non ancora utilizzabile. Così com’è, pur essendo una classe a tutti gli effetti, se istanziamo un oggetto Alunno, non potremo mai sapere come si chiama. I suoi campi istanza non saranno fruibili dal codice esterno perché così come sono stati dichiarati diventano automaticamente privati (in gergo private) alla classe e nessun codice può accedervi. Qui entrano in gioco i modificatori di accesso. Dobbiamo fare in modo che questi campi istanza diventino pubblici, cioè accessibili a tutto il codice utente. Questa è la nuova classe: class Studente { // definisco due campi istanza public string nome; public string cognome; } Finalmente ora la nostra classe è pronta per l’uso. Abbiamo inserito il modificatore public con l’intenzione di utilizzare i campi istanza all’esterno della classe e quindi dal nostro programma. Come vedremo più avanti, i campi istanza con modificatore private potranno essere comunque manipolati tramite un costrutto molto semplice. Però adesso concentriamoci sulla nostra classe e vediamo come valorizzare questi campi. Per prima cosa dovremo istanziare un oggetto dalla classe tramite il quale accederemo ai campi istanza che abbiamo creato, quindi: Studente Alunno=new Studente(); Per accedere ai campi istanza faremo uso di una particolare notazione, la notazione puntata in questo modo: Alunno.nome="Mario"; con questa istruzione, abbiamo assegnato al campo istanza nome dell’oggetto Alunno la stringa "Mario". Allo stesso modo faremo per il cognome: Alunno.cognome="Rossi"; All’assegnazione di un valore ad una variabile, ne corrisponde anche una lettura e nel nostro caso faremo l’operazione inversa; se avessimo una variabile stringa chiamata per esempio datoNome, potremo valorizzarla leggendo il valore memorizzato nel campo istanza del nostro oggetto: datoNome=Alunno.nome; i campi istanza sono delle normali variabili e quindi le possiamo manipolare come sappiamo. A questo punto della trattazione, non ci resta che scrivere qualche riga di codice per vedere in azione la nostra classe.
Copiate e compilate il codice. Questo è il risultato: Il programma appena scritto, pur non avendo nessuna utilità pratica se non quella di stampare delle stringhe, ci consente di capire come utilizzare una classe all’interno di una applicazione. Per prima cosa, notiamo dove è posizionata la classe all’interno del codice; viene posizionata subito dopo la direttiva (o le direttive) using e prima della dichiarazione della classe programma. All’interno del metodo Main(), che rappresenta il punto di inizio del programma, troviamo l’istruzione che istanzia la classe (riga 17) e quindi crea l’oggetto Alunno sul quale faremo le nostre operazioni. Le istruzioni delle righe 20 e 21 valorizzano rispettivamente il campo nome ed il campo cognome dell’oggetto. Infine alla riga 24 troviamo l’istruzione che effettua la stampa con una sintassi del tutto corretta. Nella prossima lezione, approfondiremo altri concetti molto importanti sulle classi come i metodi e le proprietà. |