Programmazione Orientata agli Oggetti (OOP)

Da Bioingegneria Elettronica e Informatica.

Introduzione

La programmazione orientata agli oggetti (OOP) consiste in un paradigma di programmazione basato sugli oggetti, ognuno delle quali è un'istanza di una classe, e queste classi sono tutte parte di una gerarchia di entità unite fra di loro da una relazione di ereditarietà. Ricapitolando:

  1. OOP utilizza un insieme di oggetti;
  2. ogni oggetto è istanza di una classe;
  3. ogni classe è legata alle altre attraverso una relazione detta eredità.

Nell'ambito della programmazione orientata agli oggetti, è necessario definire tre importanti proprietà:

  1. Incapsulamento – si basa sul principio dell’information hiding e permette di nascondere all’utente i dettagli implementativi di una classe; quindi l’utente interagisce con gli oggetti di una determinata classe attraverso le interfacce messe a disposizione dall’oggetto stesso.
  2. Ereditarietà – la possibilità per un oggetto di acquisire le caratteristiche di un’altra classe; tramite le relazioni di generalizzazione/specializzazione, una superclasse definisce un concetto generale, che viene poi specializzato dalle sottoclassi.
  3. Polimorfismo – la possibilità di utilizzare uno stesso nome per definire metodi diversi permettendo di avere accesso a diverse implementazioni di una funzione attraverso un solo nome (un’interfaccia, più metodi).

Le Classi

Alla base della programmazione ad oggetti c’è il concetto di "classe". Una classe è un costrutto utilizzato per la modellazione di entità, quindi per la creazione (istanziazione) di oggetti; quindi, un'istanza della classe si definisce “oggetto”. All'interno di una classe si possono distinguere i seguenti elementi:

  • Attributo/i;
  • Metodo/i.

Gli "attributi", o variabili membro, definiti all’interno di una classe, costituiscono lo stato della classe stessa. Un "metodo" di una classe, invece, definisce una funzionalità della classe; i metodi servono a specificare il comportamento dell’entità (ovvero l’oggetto) di cui la classe è rappresentazione. Trattandosi di funzioni, un metodo può ritornare valori, oppure nulla (come le procedure o “funzioni void”).


Ereditarietà

L'ereditarietà è il meccanismo per definire una nuova classe (classe derivata) come specializzazione di un’altra (classe base). Se la classe base modella un concetto generico, la classe derivata modella un concetto più specifico. Attraverso il principio dell'ereditarietà, la classe derivata:

  • dispone di tutte le funzionalità (attributi e metodi) di quella base;
  • può aggiungere funzionalità proprie;
  • può ridefinirne il funzionamento di metodi esistenti (polimorfismo).

In Java, si definisce una classe derivata attraverso la parola chiave “extends”, seguita dal nome della classe base.

Polimorfismo

Nell’ambito dei linguaggi di programmazione, il polimorfismo si riferisce in generale alla possibilità data ad una determinata espressione di assumere valori diversi in relazione ai tipi di dato a cui viene applicata. Il polimorfismo può essere implementato in modi diversi; i principali sono:

  • Overloading delle funzioni (method overloading): permette di "ridefinire" un medesimo metodo per set di parametri diversi (stesso nome, ma dominio diverso).
  • Ridefinizioni dei metodi ereditati (method overriding): in una sottoclasse è possibile modificare la definizione di un metodo presente nella superclasse facendo in modo tale che lo stesso metodo si comporti diversamente a seconda del tipo di oggetto su cui è invocato.

Esempio

Il codice seguente è quello relativo alla classe Persona. Come si può vedere, tale classe contiene un'unica variabile membro, una funzione costruttore (e la sua versione overloadata), e la due ulteriori funzioni.

  1. public class Persona {
  2. 	public int idp;
  3.  
  4. 	public Persona (int ID)
  5. 	{
  6. 		idp = ID;
  7. 		System.out.println("Persona costruito e suo id inizializzato a " + idp);
  8. 	}
  9.  
  10. 	public Persona ()
  11. 	{
  12. 		System.out.println("Persona costruito ma non inizializzato");
  13. 	}
  14.  
  15. 	public void stampaIDp()
  16. 	{
  17. 		System.out.println("Valore della persona stampato a " + idp);
  18. 	}
  19.  
  20. 	public void stampaIDp(int notused)
  21. 	{
  22. 		System.out.println("Valore per polimorfismo della persona stampato a " + idp);
  23. 	}
  24. }

Nelle seguenti linee di codice viene definita la classe Studente, derivata dalla classe persona, attraverso la parola chiave extends.

  1. public class Studente extends Persona {
  2. 	public int ids;
  3.  
  4. 	public Studente ()
  5. 	{
  6. 		System.out.println("Studente costruito ma non inizializzato quindi posto a ");
  7. 	}
  8.  
  9. 	public Studente (int ID)
  10. 	{
  11.                 // Richiamo il costruttore parametrizzato della classe base
  12. 		super(0);
  13.  
  14.                 // Inizializzo la variabile membro della classe Studente
  15. 		ids = ID;
  16. 		System.out.println("Studente costruito e suo id inizializzato a ");
  17. 	}
  18.  
  19. 	public void stampaIDs()
  20. 	{
  21. 		System.out.println("Valore dello studente stampato a " + ids);
  22. 	}
  23. }