prof. Nunzio Brugaletta
LinPROG

EnneBi - Programmazione
Avanti - Indietro - Inizio

La programmazione ad oggetti

Con il diffondersi del paradigma della programmazione strutturata ci si rese conto che gli obiettivi assunti come riferimento, di generare moduli indipendenti dal contesto, erano stati raggiunti solo parzialmente.

La programmazione modulare pone l'attenzione sulla suddivisione delle funzionalità che devono essere implementate in un programma ma, come ricordava anche Wirth nel suo celebre libro, Algoritmi + Strutture Dati = Programmi, gli algoritmi riguardano elaborazioni su insiemi di dati che, nella programmazione strutturata, restano fuori. Una funzione non può essere completamente esportata in un altro contesto perché fa riferimento a dati che, nel nuovo contesto, sono diversi.

La programmazione orientata agli oggetti (OOP, Object Oriented Programming) è un paradigma di programmazione, che prevede di raggruppare in un'unica entità (la classe) sia le strutture dati che le procedure che operano su di esse, creando per l'appunto un oggetto software dotato di proprietà (dati) e metodi (procedure) che operano sui dati dell'oggetto stesso.

La modularizzazione di un programma viene realizzata progettando e realizzando il codice sotto forma di classi che interagiscono tra di loro. Un programma ideale, realizzato applicando i criteri dell'OOP, sarebbe completamente costituito da oggetti software (istanze di classi) che interagiscono gli uni con gli altri. (Da Wikipedia.)

Il primo linguaggio che supportava completamente il nuovo paradigma, fu il Simula (1967), seguito dallo Smalltalk. Negli anni '80 furono create le estensioni ad oggetti per il linguaggio C e si diede vita al linguaggio C++. L'obiettivo che si pose Bjarne Stroustrup, il ricercatore danese a cui si deve l'implementazione e la definizione iniziale di C++, fu quello di non disperdere l'enorme specializzazione raggiunta dai programmatori nel linguaggio C (estremamente diffuso). Chi utilizza C++ può utilizzare la vecchie strutture sintattiche del linguaggio C e le nuove estensioni ad oggetti.

Per esporre l'utilizzo del paradigma OOP si riprende ora il problema presentato in precedenza del calcolo del totale di una fattura conoscendone le righe composte ognuna da quantità venduta e prezzo unitario.

Nel problema esposto si possono evidenziare due entità (classi) che interagiscono: la fattura e la riga. Per ognuna bisogna individuare i dati coinvolti e il tipo di operazioni richieste per quei dati:

class fattura{ 
public: 
  fattura(): totale(0.0) {};	/*1*/	 
  void aggiorna(float t){totale +=t;}; 	/*1*/ 
  friend ostream& operator<<(ostream&, const fattura&); 	/*2*/ 
protected: 
  float totale; 	/*3*/ 
}; 
ostream& operator<<(ostream& output, const fattura& f)	/*2*/	 
{ 	 
  output << "Totale fattura: " << f.totale << endl; 
  return output; 
};

la classe fattura, per quanto richiesto dal problema da risolvere, è provvista della proprietà totale (3) e dei metodi (1) per il trattamento del dato. Nel caso specifico è previsto un metodo per l'inizializzazione e un altro per l'aggiornamento. È possibile anche ridefinire l'operatore per l'output (<<) in modo da adattarsi alle istanze della classe (2).

class riga{ 
public: 
  void nuova(int, float); 	/*1*/
  float totriga(); 	/*1*/
  friend ostream& operator<<(ostream&, const riga&); 	/*2*/ 
protected: 
  int qv; 	/*3*/
  float pu; 	/*3*/
}; 

ostream& operator<<(ostream& output, const riga& r)	/*2*/	 
{ 
  output << "Quantita\' venduta: " << r.qv 
         << " Prezzo unitario: " << r.pu << endl; 
  return output; 
}; 

// metodo per inserimento di una nuova riga 

void riga::nuova(int q, float p)	/*1*/	 
{ 
  qv = q; 
  pu = p; 
}; 

// metodo per il calcolo del totale della riga 

float riga::totriga()	/*1*/	 
{ 
  float tr; 
  tr = (float) qv*pu; 
  return tr; 
}; 

Per la classe riga sono definiti (3) gli attributi quantità venduta (qv) e prezzo unitario (pu) e i metodi (1) per la generazione di una nuova riga e per il calcolo del totale della riga. Anche per le istanze della classe è definito (2) l'operatore di output.

Tutto quello che riguarda la fattura o la riga della fattura è inserito nella rispettiva classe. La classe può essere utilizzata in un qualsiasi contesto che necessiti di una fattura o delle caratteristiche di una riga. La OOP è dotata di meccanismi che permettono di adattare, aggiungendo e specificando ma senza avere necessità di modifiche del codice esistente, la classe a nuove esigenze. Per esempio se si dovesse avere l'esigenza, in una diversa elaborazione, di calcolare lo sconto su ogni riga, il codice per lo sconto può essere aggiunto con un sistema del tipo: oltre alle caratteristiche già esistenti aggiungi anche queste altre o modifica, in questo modo, quelle altre.

Nel programma, che utilizza le classi, interagiscono istanze (oggetti) delle varie classi. Ogni oggetto in quanto appartenente alla classe ne gode di tutte le proprietà. I metodi rappresentano delle competenze di tutti gli oggetti della classe:

#include <iostream> 
#include “c_fattura”	/*1*/	 
#include “c_riga”	/*1*/ 
using namespace std; 

int main() 
{ 
  int qvend,i; 
  float pzunit; 
  riga r;	/*2*/	 
  fattura f;	/*2*/ 

  // elaborazione righe fattura 

  for(i=1;;i++){	 
    cout << "Riga n. " << i << endl;	 
    cout << "Quantita\'_venduta prezzo_unitario (0 0 per finire) "; 
    cin >> qvend >> pzunit; 

    if((qvend<=0) || (pzunit<=0))	 
      break;	 

    r.nuova(qvend,pzunit);	/*3*/	 
    cout << r;	/*4*/ 
    f.aggiorna(r.totriga());	/*3*/ 
  }; 

  // stampa fattura 

  cout << f;	/*4*/	 

  return 0; 
}

Dopo aver incluso nel programma anche il codice delle due classi (1), si possono dichiarare (2) oggetti delle classi definite. I due oggetti r ed f hanno le caratteristiche definite per le rispettive classi: r è una riga come la si intende nella classe riga così come f è una fattura per come si intende nella classe. Con gli oggetti si interagisce inviando messaggi (3). L'oggetto risponde per come definito dal metodo: la generazione di una nuova riga e l'aggiornamento del totale della fattura con il totale della righe.



Avanti - Indietro - Inizio

http://ennebi.solira.org
ennebi@solira.org