CodeGym /Corsi /C# SELF /Sovraccarico dei costruttori

Sovraccarico dei costruttori

C# SELF
Livello 16 , Lezione 4
Disponibile

1. Introduzione

Supponiamo di avere una classe Person:

public class Person
{
    public string Name;
    public int Age;
    
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

E ti senti quasi un genio — puoi creare persone con qualsiasi nome ed età. Ma ecco il problema: a volte le informazioni non bastano! L’utente dell’app ha inserito solo il nome, e l’età per qualche motivo si sa solo dopo. Oppure vuoi, in certi casi, assegnare un’età "standard" di default. Certo, si possono inventare workaround, ma C# ti dà una soluzione elegante — sovraccarico dei costruttori.

Sovraccarico dei costruttori significa che una classe può avere più costruttori con lo stesso nome (il nome della classe), ma con liste di parametri diverse.

Qual è la differenza tra queste liste? Possono differire per:

  1. Numero di parametri: Per esempio, un costruttore prende 2 parametri, un altro — 3.
  2. Tipi di parametri: Uno prende (string, int), un altro — (string, decimal).
  3. Ordine dei parametri: (string, int) e (int, string) — sono firme diverse.

La regola più importante: il compilatore distingue i costruttori (e qualsiasi metodo) dalla loro firma. La firma include il nome del costruttore (o del metodo) e la lista dei suoi parametri (numero, tipi e ordine). I modificatori di accesso (public, private) e, per i metodi normali, il tipo di ritorno, non fanno parte della firma. Ma i costruttori non hanno tipo di ritorno, e il nome è sempre quello della classe.

2. Sovraccarico dei costruttori: sintassi ed esempio


public class Cat
{
    public string Name;
    public string Color;

    // Costruttore senza parametri
    public Cat()
    {
        Name = "Gatto senza nome";
        Color = "Grigio";
    }

    // Costruttore con un parametro
    public Cat(string name)
    {
        Name = name;
        Color = "Grigio";
    }

    // Costruttore con due parametri
    public Cat(string name, string color)
    {
        Name = name;
        Color = color;
    }
}

Utilizzo:

Cat barsik = new Cat(); // "Gatto senza nome", "Grigio"
Cat murzik = new Cat("Murzik"); // "Murzik", "Grigio"
Cat ryzhik = new Cat("Ryzhik", "Rosso"); // "Ryzhik", "Rosso"

Se quando crei un oggetto passi dei parametri, C# "indovina" il costruttore giusto in base a quanti e che tipo sono.

Comodissimo! L’utente della tua classe non deve specificare parametri che non conosce: se vuole solo un gatto — prende il costruttore senza parametri, se sa il nome — usa l’altro, e così via. Vuole il controllo totale sul colore — prende la terza opzione.

3. Come funziona la chiamata dei costruttori sovraccaricati?

C# sceglie il costruttore giusto automaticamente in fase di compilazione, in base al tipo e al numero di argomenti passati. Sbagliare è difficile — se qualcosa non va, il compilatore ti sgrida subito.

Proviamo ad aggiungere un costruttore con un parametro intero:

public Cat(int age)
{
    Name = "Gatto senza nome";
    Color = "Grigio";
    // Codice aggiuntivo per l’età
}

Ora possiamo creare anche un "gattino per età":

Cat oldCat = new Cat(5); // Verrà chiamato Cat(int age)
Chiamata del costruttore Quale viene chiamato?
new Cat()
Senza parametri
new Cat("Murka")
Con un parametro stringa
new Cat("Ryzhik", "Rosso")
Con due parametri stringa
new Cat(10)
Con un parametro intero

4. Chiamate interne ai costruttori: parola chiave this

Capita che costruttori diversi facciano cose simili (o uguali). Per non copiare codice, puoi "chiamare un costruttore dall’altro". Per questo si usa la parola chiave this.


public class Cat
{
    public string Name;
    public string Color;

    public Cat() : this("Gatto senza nome")
    {
        // Questo costruttore chiama Cat(string name)
    }

    public Cat(string name) : this(name, "Grigio")
    {
        // Questo costruttore chiama Cat(string name, string color)
    }

    public Cat(string name, string color)
    {
        Name = name;
        Color = color;
    }
}

Alla fine:

  • new Cat() chiama Cat(string name), che chiama Cat(string name, string color).
  • Tutte le "strade portano a Roma": cioè tutta l’inizializzazione è concentrata in un unico costruttore "principale".

Questo approccio si chiama constructor chaining (catena di chiamate dei costruttori).

5. Esempi dalla vita reale

Creiamo una classe eroe (Hero) per un gioco, con nome e livello! Ecco come la scriveremmo:

Con un solo costruttore:

public class Hero
{
    public string Name;
    public int Level;

    public Hero(string name, int level)
    {
        Name = name;
        Level = level;
    }
}

E ora permettiamo di crearlo in modi diversi!

Tanti costruttori:

public class Hero
{
    public string Name;
    public int Level;

    // Se non si specifica nulla, l’eroe sarà "Senza nome" di livello 1
    public Hero() : this("Senza nome", 1)
    {
    }

    // Se sappiamo solo il nome, livello di default — 1
    public Hero(string name) : this(name, 1)
    {
    }

    // Il costruttore principale con due parametri
    public Hero(string name, int level)
    {
        Name = name;
        Level = level;
    }
}

Ora puoi creare l’eroe in vari modi:

Hero h1 = new Hero();               // "Senza nome", 1
Hero h2 = new Hero("Artur");        // "Artur", 1
Hero h3 = new Hero("Lora", 10);     // "Lora", 10

6. Dettagli di implementazione: trappole nascoste e sfumature

Primo: il compilatore non crea un costruttore "vuoto" di default se ne hai dichiarato almeno uno con parametri. Quindi, se hai scritto un costruttore con parametri ma ti sei dimenticato quello senza, questa chiamata:

Hero h = new Hero(); // Errore, se manca il costruttore senza parametri!
darà errore di compilazione.

Secondo: se nella catena di chiamate chiami il costruttore sbagliato, puoi rompere la logica di inizializzazione. È importante essere coerenti: meglio che tutto il lavoro reale sia fatto dal costruttore più completo, e gli altri passino solo i dati tramite this(...).

Terzo: se i parametri differiscono solo per tipo (tipo Cat(string s) e Cat(object o)), puoi incasinarti quando chiami il costruttore con un argomento null. Il compilatore non sempre capisce quale vuoi chiamare.

7. Sovraccarico e inizializzazione dei campi

Spesso in una classe ci sono campi che vanno per forza impostati. Il sovraccarico dei costruttori aiuta a farlo in modo comodo, ma sei tu a decidere quali valori di default hanno senso per la tua classe.

Esempio con controllo:

public class Book
{
    public string Title;
    public int Year;

    // Libro di default — "Senza titolo", anno 2000
    public Book() : this("Senza titolo", 2000)
    {
    }
    
    public Book(string title) : this(title, 2000)
    {
    }

    public Book(string title, int year)
    {
        Title = title;
        Year = year;
    }
}

8. Sovraccarico con set diversi di parametri

Capita di vedere classi con decine di costruttori! Non sempre è segno di buona architettura (a volte meglio usare metodi di configurazione o pattern "builder"), ma per oggetti utente, modelli, DTO — va benissimo.

Esempio: classe "Pet", dove puoi specificare tutte le caratteristiche, oppure solo le più importanti.

public class Pet
{
    public string Name;
    public int Age;
    public string Type;
    public bool IsVaccinated;

    // Costruttore di default
    public Pet() : this("NoName", 0, "Cat", false) { }

    // Minimo di info
    public Pet(string name, string type) : this(name, 0, type, false) { }

    // Costruttore completo
    public Pet(string name, int age, string type, bool isVaccinated)
    {
        Name = name;
        Age = age;
        Type = type;
        IsVaccinated = isVaccinated;
    }
}
Differenza tra sovraccarico di metodo e costruttore
Metodo normale Costruttore (anche sovraccaricato)
Puoi chiamarlo quando vuoi Viene chiamato solo quando crei l’oggetto (new)
Può restituire valori di qualsiasi tipo Non restituisce mai un valore (nessun tipo specificato)
Il nome può essere qualsiasi, spesso un verbo Il nome è sempre quello della classe
Puoi sovraccaricarlo sui parametri Si sovraccarica anche sui parametri
1
Sondaggio/quiz
Concetto di classe e oggetto, livello 16, lezione 4
Non disponibile
Concetto di classe e oggetto
Classi e costruttori
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION