☕ Lezione 3

Costruttori e la Parola Chiave this

Costruttori: Inizializzare gli Oggetti

🎯 Obiettivi della lezione

💡 Cos'è un Costruttore?

Un costruttore è un metodo speciale che viene chiamato automaticamente quando creiamo un nuovo oggetto con new.

Serve per inizializzare gli attributi dell'oggetto al momento della creazione.

🔍 Problema Senza Costruttore

Nella lezione precedente, inizializzavamo gli oggetti così:

Studente studente1 = new Studente();
studente1.nome = "Mario";
studente1.cognome = "Rossi";
studente1.eta = 17;
studente1.mediaVoti = 7.5;

⚠️ Problemi di questo approccio:

  • Molte righe di codice ripetitive
  • Possiamo dimenticare di inizializzare alcuni attributi
  • Rischio di errori se sbagliamo a scrivere il nome
  • Codice poco elegante e meno manutenibile

✅ Soluzione: Il Costruttore

Con un costruttore, possiamo fare tutto in una riga:

Studente studente1 = new Studente("Mario", "Rossi", 17, 7.5);

📝 Sintassi del Costruttore

Caratteristiche di un costruttore:

  • Ha lo stesso nome della classe
  • NON ha tipo di ritorno (nemmeno void)
  • Può avere parametri (o nessuno)
  • Viene chiamato automaticamente con new

🏗️ Classe Studente con Costruttore

public class Studente {
    // Attributi
    String nome;
    String cognome;
    int eta;
    double mediaVoti;
    
    // COSTRUTTORE
    public Studente(String n, String c, int e, double m) {
        nome = n;
        cognome = c;
        eta = e;
        mediaVoti = m;
    }
    
    // Metodi
    void stampaInfo() {
        System.out.println("Nome: " + nome + " " + cognome);
        System.out.println("Età: " + eta);
        System.out.println("Media: " + mediaVoti);
    }
    
    boolean ePromosso() {
        return mediaVoti >= 6.0;
    }
}

🎨 Uso del Costruttore

public class TestStudente {
    public static void main(String[] args) {
        // Creo oggetti usando il costruttore
        Studente s1 = new Studente("Mario", "Rossi", 17, 7.5);
        Studente s2 = new Studente("Giulia", "Bianchi", 16, 8.2);
        Studente s3 = new Studente("Luca", "Verdi", 17, 5.8);
        
        // Stampo le informazioni
        s1.stampaInfo();
        System.out.println("Promosso: " + s1.ePromosso());
        System.out.println();
        
        s2.stampaInfo();
        System.out.println("Promosso: " + s2.ePromosso());
        System.out.println();
        
        s3.stampaInfo();
        System.out.println("Promosso: " + s3.ePromosso());
    }
}
Nome: Mario Rossi Età: 17 Media: 7.5 Promosso: true Nome: Giulia Bianchi Età: 16 Media: 8.2 Promosso: true Nome: Luca Verdi Età: 17 Media: 5.8 Promosso: false

🔑 La Parola Chiave THIS

this è un riferimento all'oggetto corrente, cioè l'oggetto su cui stiamo lavorando in quel momento.

Si usa principalmente quando il nome del parametro è uguale al nome dell'attributo.

📝 Costruttore con this

Vediamo come migliorare il costruttore usando this:

public class Studente {
    // Attributi
    String nome;
    String cognome;
    int eta;
    double mediaVoti;
    
    // COSTRUTTORE CON THIS
    public Studente(String nome, String cognome, int eta, double mediaVoti) {
        // this.nome si riferisce all'attributo della classe
        // nome (senza this) si riferisce al parametro
        this.nome = nome;
        this.cognome = cognome;
        this.eta = eta;
        this.mediaVoti = mediaVoti;
    }
    
    void stampaInfo() {
        System.out.println("Nome: " + this.nome + " " + this.cognome);
        System.out.println("Età: " + this.eta);
        System.out.println("Media: " + this.mediaVoti);
    }
}

✅ Vantaggi di usare this:

  • Possiamo usare nomi più chiari per i parametri
  • Evitiamo confusione tra attributi e parametri
  • Il codice è più leggibile

🔄 Overloading dei Costruttori

L'overloading significa creare più costruttori con parametri diversi.

Java sceglie automaticamente quale costruttore usare in base ai parametri che passiamo!

📝 Esempio di Overloading

public class Libro {
    String titolo;
    String autore;
    int pagine;
    double prezzo;
    
    // Costruttore 1: tutti i parametri
    public Libro(String titolo, String autore, int pagine, double prezzo) {
        this.titolo = titolo;
        this.autore = autore;
        this.pagine = pagine;
        this.prezzo = prezzo;
    }
    
    // Costruttore 2: solo titolo e autore
    public Libro(String titolo, String autore) {
        this.titolo = titolo;
        this.autore = autore;
        this.pagine = 0;      // Valore di default
        this.prezzo = 0.0;    // Valore di default
    }
    
    // Costruttore 3: solo titolo
    public Libro(String titolo) {
        this.titolo = titolo;
        this.autore = "Sconosciuto";
        this.pagine = 0;
        this.prezzo = 0.0;
    }
    
    // Costruttore 4: senza parametri (costruttore di default)
    public Libro() {
        this.titolo = "Da definire";
        this.autore = "Da definire";
        this.pagine = 0;
        this.prezzo = 0.0;
    }
    
    void stampaInfo() {
        System.out.println("Titolo: " + titolo);
        System.out.println("Autore: " + autore);
        System.out.println("Pagine: " + pagine);
        System.out.println("Prezzo: €" + prezzo);
        System.out.println("---");
    }
}

🧪 Uso dei Diversi Costruttori

public class TestLibro {
    public static void main(String[] args) {
        // Uso costruttore con tutti i parametri
        Libro libro1 = new Libro("1984", "George Orwell", 328, 12.50);
        
        // Uso costruttore con titolo e autore
        Libro libro2 = new Libro("Il Signore degli Anelli", "J.R.R. Tolkien");
        
        // Uso costruttore con solo titolo
        Libro libro3 = new Libro("Harry Potter");
        
        // Uso costruttore senza parametri
        Libro libro4 = new Libro();
        
        libro1.stampaInfo();
        libro2.stampaInfo();
        libro3.stampaInfo();
        libro4.stampaInfo();
    }
}
Titolo: 1984 Autore: George Orwell Pagine: 328 Prezzo: €12.5 --- Titolo: Il Signore degli Anelli Autore: J.R.R. Tolkien Pagine: 0 Prezzo: €0.0 --- Titolo: Harry Potter Autore: Sconosciuto Pagine: 0 Prezzo: €0.0 --- Titolo: Da definire Autore: Da definire Pagine: 0 Prezzo: €0.0 ---

🔗 Chiamare un Costruttore da un Altro

Possiamo usare this() per chiamare un altro costruttore della stessa classe:

public class Libro {
    String titolo;
    String autore;
    int pagine;
    double prezzo;
    
    // Costruttore principale
    public Libro(String titolo, String autore, int pagine, double prezzo) {
        this.titolo = titolo;
        this.autore = autore;
        this.pagine = pagine;
        this.prezzo = prezzo;
    }
    
    // Costruttore che chiama quello principale
    public Libro(String titolo, String autore) {
        this(titolo, autore, 0, 0.0);  // Chiama il costruttore sopra
    }
    
    // Costruttore che chiama quello con 2 parametri
    public Libro(String titolo) {
        this(titolo, "Sconosciuto");  // Chiama il costruttore sopra
    }
    
    // Costruttore che chiama quello con 1 parametro
    public Libro() {
        this("Da definire");  // Chiama il costruttore sopra
    }
}

✅ Vantaggi:

  • Evita duplicazione di codice
  • Più facile da manutenere
  • Se cambio la logica, la cambio in un solo posto

⚠️ Attenzione!

La chiamata this() deve essere la prima istruzione nel costruttore!

🚗 Esempio Completo: Classe Auto

public class Auto {
    String marca;
    String modello;
    int anno;
    double chilometraggio;
    String colore;
    
    // Costruttore completo
    public Auto(String marca, String modello, int anno, 
                double chilometraggio, String colore) {
        this.marca = marca;
        this.modello = modello;
        this.anno = anno;
        this.chilometraggio = chilometraggio;
        this.colore = colore;
    }
    
    // Costruttore per auto nuova (km = 0)
    public Auto(String marca, String modello, int anno, String colore) {
        this(marca, modello, anno, 0.0, colore);
    }
    
    // Costruttore base
    public Auto(String marca, String modello) {
        this(marca, modello, 2024, "Bianco");
    }
    
    void stampaInfo() {
        System.out.println("=== Auto ===");
        System.out.println("Marca: " + this.marca);
        System.out.println("Modello: " + this.modello);
        System.out.println("Anno: " + this.anno);
        System.out.println("Km: " + this.chilometraggio);
        System.out.println("Colore: " + this.colore);
        System.out.println();
    }
    
    void percorri(double km) {
        this.chilometraggio += km;
        System.out.println("Hai percorso " + km + " km. " +
                         "Totale: " + this.chilometraggio + " km");
    }
}
public class TestAuto {
    public static void main(String[] args) {
        Auto auto1 = new Auto("Fiat", "500", 2020, 45000, "Rosso");
        Auto auto2 = new Auto("Toyota", "Yaris", 2023, "Blu");
        Auto auto3 = new Auto("BMW", "X3");
        
        auto1.stampaInfo();
        auto2.stampaInfo();
        auto3.stampaInfo();
        
        auto3.percorri(150);
        auto3.percorri(200);
    }
}
=== Auto === Marca: Fiat Modello: 500 Anno: 2020 Km: 45000.0 Colore: Rosso === Auto === Marca: Toyota Modello: Yaris Anno: 2023 Km: 0.0 Colore: Blu === Auto === Marca: BMW Modello: X3 Anno: 2024 Km: 0.0 Colore: Bianco Hai percorso 150.0 km. Totale: 150.0 km Hai percorso 200.0 km. Totale: 350.0 km

✏️ Esercizi Guidati

Esercizio 1: Classe Persona con Costruttori

FACILE

Obiettivo: Creare una classe Persona con più costruttori.

Requisiti:

  1. Attributi: nome, cognome, eta, citta
  2. Costruttore con tutti i parametri
  3. Costruttore con nome, cognome, eta (città = "Non specificata")
  4. Costruttore con nome, cognome (eta = 0, città = "Non specificata")
  5. Metodo stampaInfo()

Codice iniziale:

public class Persona {
    String nome;
    String cognome;
    int eta;
    String citta;
    
    // Costruttore completo
    public Persona(String nome, String cognome, int eta, String citta) {
        // Completa usando this
    }
    
    // Costruttore senza città
    public Persona(String nome, String cognome, int eta) {
        // Completa chiamando l'altro costruttore con this()
    }
    
    // Costruttore solo nome e cognome
    public Persona(String nome, String cognome) {
        // Completa
    }
    
    void stampaInfo() {
        // Completa
    }
}

Esercizio 2: Classe Punto2D

MEDIO

Obiettivo: Creare una classe per rappresentare un punto nel piano cartesiano.

Requisiti:

  • Attributi: x (double), y (double)
  • Costruttore con x e y
  • Costruttore senza parametri (origine: x=0, y=0)
  • Metodo distanzaDaOrigine() che restituisce la distanza dall'origine usando il teorema di Pitagora: √(x² + y²)
  • Metodo distanzaDa(Punto2D altro) che calcola la distanza da un altro punto
  • Metodo stampa() che mostra le coordinate

Suggerimenti:

  • Usa Math.sqrt() per la radice quadrata
  • Usa Math.pow(x, 2) per elevare al quadrato

💪 Esercizi da Svolgere

Esercizio 3: Classe ContoBancario

MEDIO

Crea una classe ContoBancario con:

  • Attributi: numeroConto, intestatario, saldo
  • Costruttore con numeroConto e intestatario (saldo iniziale = 0)
  • Costruttore con numeroConto, intestatario e saldo iniziale
  • Metodi: deposita(), preleva(), visualizzaSaldo()

Esercizio 4: Classe Film

FACILE

Crea una classe Film con:

  • Attributi: titolo, regista, anno, durata (in minuti)
  • Tre costruttori diversi con livelli crescenti di dettaglio
  • Metodo per convertire la durata in ore e minuti
  • Metodo per stampare tutte le informazioni

Esercizio 5: Classe Rettangolo

MEDIO

Crea una classe Rettangolo con:

  • Attributi: base, altezza
  • Costruttore con base e altezza
  • Costruttore che crea un quadrato (un solo parametro lato)
  • Costruttore senza parametri (rettangolo 1x1)
  • Metodi: calcolaArea(), calcolaPerimetro(), eQuadrato()

Esercizio 6: Classe Cerchio

FACILE

Crea una classe Cerchio con:

  • Attributo: raggio
  • Costruttore con il raggio
  • Costruttore senza parametri (raggio = 1)
  • Metodo per calcolare area e circonferenza

🎯 Concetti Chiave da Ricordare

  • Il costruttore inizializza gli attributi quando creiamo un oggetto
  • Il costruttore ha lo stesso nome della classe e NO tipo di ritorno
  • this si riferisce all'oggetto corrente
  • Possiamo creare più costruttori con parametri diversi (overloading)
  • this() chiama un altro costruttore (deve essere la prima istruzione)
  • Se non creiamo nessun costruttore, Java ne crea uno vuoto di default

🔍 Confronto: Costruttore vs Metodo

Caratteristica Costruttore Metodo
Nome Stesso nome della classe Qualsiasi nome
Tipo di ritorno NESSUNO (nemmeno void) void o un tipo specifico
Chiamata Automatica con new Manuale con nomeOggetto.metodo()
Scopo Inizializzare l'oggetto Eseguire operazioni