Programmazione Orientata agli Oggetti
La Programmazione Orientata agli Oggetti (OOP) è un paradigma che modella il software come una collezione di oggetti che interagiscono tra loro. Ogni oggetto rappresenta un'entità del mondo reale con stato (attributi) e comportamento (metodi).
Cosa Imparerai
- Cos'è una classe e cos'è un oggetto
- Stato e comportamento
- Costruttori e inizializzazione
- Incapsulamento e modificatori di accesso
- La parola chiave this
- Membri statici vs di istanza
Classi e Oggetti
Definizioni Chiave
- Classe: Un modello (blueprint) che definisce attributi e metodi
- Oggetto: Un'istanza di una classe, un'entità concreta in memoria
- Attributi: Variabili che rappresentano lo stato dell'oggetto
- Metodi: Funzioni che definiscono il comportamento dell'oggetto
// Definizione della classe
public class Studente {
// Attributi (stato)
String nome;
String cognome;
int matricola;
int annoCorso;
double mediaVoti;
// Metodi (comportamento)
void presentati() {
System.out.println("Ciao, sono " + nome + " " + cognome);
System.out.println("Matricola: " + matricola);
}
void studiaMateria(String materia) {
System.out.println(nome + " sta studiando " + materia);
}
boolean isFuoriCorso() {
return annoCorso > 3;
}
}
public class Main {
public static void main(String[] args) {
// Creazione oggetto con new
Studente mario = new Studente();
// Assegnazione attributi
mario.nome = "Mario";
mario.cognome = "Rossi";
mario.matricola = 123456;
mario.annoCorso = 2;
mario.mediaVoti = 27.5;
// Chiamata metodi
mario.presentati();
mario.studiaMateria("Programmazione");
// Creare più oggetti dalla stessa classe
Studente luigi = new Studente();
luigi.nome = "Luigi";
luigi.cognome = "Verdi";
luigi.matricola = 789012;
// Ogni oggetto ha il proprio stato
System.out.println(mario.nome); // Mario
System.out.println(luigi.nome); // Luigi
}
}
Costruttori
Un costruttore e un metodo speciale chiamato quando si crea
un oggetto con new. Permette di inizializzare l'oggetto.
public class Studente {
String nome;
String cognome;
int matricola;
int annoCorso;
// Costruttore di default (senza parametri)
public Studente() {
this.annoCorso = 1; // valore predefinito
}
// Costruttore con parametri
public Studente(String nome, String cognome, int matricola) {
this.nome = nome;
this.cognome = cognome;
this.matricola = matricola;
this.annoCorso = 1;
}
// Costruttore completo
public Studente(String nome, String cognome, int matricola, int annoCorso) {
this.nome = nome;
this.cognome = cognome;
this.matricola = matricola;
this.annoCorso = annoCorso;
}
}
// Utilizzo dei costruttori
Studente s1 = new Studente(); // costruttore di default
Studente s2 = new Studente("Mario", "Rossi", 123456); // costruttore con 3 parametri
Studente s3 = new Studente("Luigi", "Verdi", 789012, 2); // costruttore completo
Regole sui Costruttori
- Il nome del costruttore deve essere identico al nome della classe
- Non ha tipo di ritorno (nemmeno void)
- Se non definisci nessun costruttore, Java crea un costruttore di default vuoto
- Se definisci un costruttore con parametri, il costruttore di default non viene più creato automaticamente
Incapsulamento
L'incapsulamento protegge i dati di un oggetto nascondendoli dall'esterno e fornendo metodi controllati per accedervi (getter/setter).
public class ContoBancario {
// private: accessibile solo dentro la classe
private double saldo;
private String intestatario;
// public: accessibile da ovunque
public ContoBancario(String intestatario, double saldoIniziale) {
this.intestatario = intestatario;
this.saldo = saldoIniziale;
}
// Getter: permette di LEGGERE il valore
public double getSaldo() {
return saldo;
}
public String getIntestatario() {
return intestatario;
}
// Setter con validazione
public void deposita(double importo) {
if (importo > 0) {
saldo += importo;
System.out.println("Depositati €" + importo);
} else {
System.out.println("Importo non valido");
}
}
public boolean preleva(double importo) {
if (importo > 0 && importo <= saldo) {
saldo -= importo;
System.out.println("Prelevati €" + importo);
return true;
}
System.out.println("Prelievo non autorizzato");
return false;
}
}
Modificatori di Accesso
| Modificatore | Classe | Package | Sottoclasse | Ovunque |
|---|---|---|---|---|
| private | ✅ | ❌ | ❌ | ❌ |
| (default) | ✅ | ✅ | ❌ | ❌ |
| protected | ✅ | ✅ | ✅ | ❌ |
| public | ✅ | ✅ | ✅ | ✅ |
La Parola Chiave this
public class Corso {
private String nome;
private int crediti;
private Docente docente;
// this per distinguere parametri da attributi
public Corso(String nome, int crediti) {
this.nome = nome; // this.nome = attributo
this.crediti = crediti; // nome = parametro
}
// this per chiamare un altro costruttore
public Corso(String nome) {
this(nome, 6); // chiama il costruttore con 2 parametri
}
// this per passare l'oggetto corrente
public void assegnaDocente(Docente docente) {
this.docente = docente;
docente.aggiungiCorso(this); // passa questo corso al docente
}
// this per catene di metodi (fluent interface)
public Corso conCrediti(int crediti) {
this.crediti = crediti;
return this;
}
public Corso conDocente(Docente docente) {
this.docente = docente;
return this;
}
}
// Uso fluent interface
Corso corso = new Corso("Programmazione")
.conCrediti(9)
.conDocente(profRossi);
Membri Statici vs Istanza
public class Studente {
// Attributo STATICO: condiviso da tutte le istanze
private static int contatore = 0;
private static final String UNIVERSITA = "Universita di Bologna";
// Attributi di ISTANZA: uno per ogni oggetto
private int matricola;
private String nome;
public Studente(String nome) {
this.nome = nome;
contatore++; // incrementa per ogni nuovo studente
this.matricola = 2024000 + contatore;
}
// Metodo STATICO: appartiene alla classe, non all'istanza
public static int getNumeroStudenti() {
return contatore;
}
public static String getUniversita() {
return UNIVERSITA;
}
// Metodo di ISTANZA: opera su un oggetto specifico
public void presentati() {
System.out.println("Sono " + nome + " di " + UNIVERSITA);
}
}
// Utilizzo
System.out.println(Studente.getUniversita()); // Chiamata statica
Studente s1 = new Studente("Mario");
Studente s2 = new Studente("Luigi");
System.out.println(Studente.getNumeroStudenti()); // 2
s1.presentati(); // Chiamata su istanza
Quando usare static
- Costanti:
static finalper valori immutabili condivisi - Contatori: Per tenere traccia del numero di istanze
- Utility: Metodi che non dipendono dallo stato dell'oggetto (es. Math.sqrt())
- Factory: Metodi che creano istanze della classe
Esempio Completo: Sistema Gestione Corsi
package it.universita.gestione;
public class Studente {
// Attributi statici
private static int contatore = 0;
// Attributi di istanza
private final int matricola;
private String nome;
private String cognome;
private int annoIscrizione;
private double mediaVoti;
private int esamiSostenuti;
// Costruttore
public Studente(String nome, String cognome, int annoIscrizione) {
this.matricola = generaMatricola();
this.nome = nome;
this.cognome = cognome;
this.annoIscrizione = annoIscrizione;
this.mediaVoti = 0;
this.esamiSostenuti = 0;
}
// Metodo statico privato
private static int generaMatricola() {
contatore++;
return 2024000 + contatore;
}
// Getter
public int getMatricola() {
return matricola;
}
public String getNomeCompleto() {
return nome + " " + cognome;
}
public double getMediaVoti() {
return mediaVoti;
}
// Metodo per registrare un esame
public void registraEsame(int voto) {
if (voto >= 18 && voto <= 30) {
double totale = mediaVoti * esamiSostenuti;
esamiSostenuti++;
mediaVoti = (totale + voto) / esamiSostenuti;
System.out.printf("%s ha superato l'esame con %d%n", getNomeCompleto(), voto);
} else {
System.out.println("Voto non valido");
}
}
// Metodo per calcolare l'anno di corso
public int getAnnoCorso() {
int annoCorrente = java.time.Year.now().getValue();
return annoCorrente - annoIscrizione + 1;
}
public boolean isFuoriCorso() {
return getAnnoCorso() > 3;
}
// toString per rappresentazione stringa
@Override
public String toString() {
return String.format("Studente[matricola=%d, nome=%s, media=%.2f, anno=%d]",
matricola, getNomeCompleto(), mediaVoti, getAnnoCorso());
}
// Metodo statico di utilita
public static int getTotaleStudenti() {
return contatore;
}
}
package it.universita.gestione;
public class Esame {
private String nomeCorso;
private int crediti;
private Studente studente;
private int voto;
private boolean lode;
private String data;
public Esame(String nomeCorso, int crediti, Studente studente) {
this.nomeCorso = nomeCorso;
this.crediti = crediti;
this.studente = studente;
}
public void registraVoto(int voto, boolean lode) {
if (voto >= 18 && voto <= 30) {
this.voto = voto;
this.lode = (voto == 30 && lode);
this.data = java.time.LocalDate.now().toString();
studente.registraEsame(voto);
}
}
public String getVotoFormattato() {
if (voto == 0) return "Non sostenuto";
return lode ? "30 e Lode" : String.valueOf(voto);
}
@Override
public String toString() {
return String.format("%s - %s: %s (%d CFU)",
studente.getNomeCompleto(), nomeCorso, getVotoFormattato(), crediti);
}
}
package it.universita.gestione;
public class TestGestione {
public static void main(String[] args) {
// Creazione studenti
Studente mario = new Studente("Mario", "Rossi", 2023);
Studente luigi = new Studente("Luigi", "Verdi", 2022);
// Registrazione esami
Esame esameProgrammazione = new Esame("Programmazione", 9, mario);
esameProgrammazione.registraVoto(28, false);
Esame esameAnalisi = new Esame("Analisi I", 12, mario);
esameAnalisi.registraVoto(30, true);
Esame esameReti = new Esame("Reti", 6, luigi);
esameReti.registraVoto(25, false);
// Stampa situazione
System.out.println("\n=== Situazione Studenti ===");
System.out.println(mario);
System.out.println(luigi);
System.out.println("\n=== Esami Registrati ===");
System.out.println(esameProgrammazione);
System.out.println(esameAnalisi);
System.out.println(esameReti);
System.out.println("\n=== Statistiche ===");
System.out.println("Totale studenti: " + Studente.getTotaleStudenti());
}
}
Conclusione
In questo articolo abbiamo introdotto i concetti fondamentali della OOP: classi, oggetti, costruttori, incapsulamento e membri statici.
Nel prossimo articolo approfondiremo ereditarieta, polimorfismo e interfacce: i pilastri avanzati della programmazione a oggetti.
Punti Chiave da Ricordare
- Classe: Blueprint che definisce attributi e metodi
- Oggetto: Istanza concreta di una classe
- Costruttore: Metodo speciale per inizializzare oggetti
- Incapsulamento: Nascondi i dati, esponi metodi controllati
- this: Riferimento all'oggetto corrente
- static: Appartiene alla classe, non alle istanze
Domande frequenti
Cos'è la Programmazione Orientata agli Oggetti (OOP)?
La Programmazione Orientata agli Oggetti è un paradigma che modella il software come una collezione di oggetti che interagiscono tra loro.
Quali sono le caratteristiche principali degli oggetti in OOP?
Gli oggetti rappresentano un'entità del mondo reale con stato (attributi) e comportamento (metodi).
Cosa è il costruttore in OOP?
Il costruttore è un metodo speciale chiamato quando si crea un oggetto, che permette di inizializzare l'oggetto.
Qual è lo scopo dell'incapsulamento in OOP?
L'incapsulamento protegge i dati di un oggetto nascondendoli dall'esterno e fornendo metodi controllati per accedervi.

Commenti
Caricamento commenti...
Accedi per commentare