CodeGym /Cursos /C# SELF /Sobrecarga de constructores

Sobrecarga de constructores

C# SELF
Nivel 16 , Lección 4
Disponible

1. Introducción

Supón que tenemos una clase Person:

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

Y aquí te sientes casi un genio — puedes crear personas con cualquier nombre y edad. Pero hay un problema: ¡a veces no hay suficiente información! El usuario de la app solo metió el nombre, y la edad por alguna razón se sabe después. O quieres en algunos casos poner una edad "estándar" por defecto. Claro, podrías buscarte la vida, pero C# te da una solución elegante para esto — sobrecarga de constructores.

Sobrecarga de constructores significa que una clase puede tener varios constructores con el mismo nombre (el nombre de la clase), pero con diferentes listas de parámetros.

¿En qué se diferencian esas listas? Pueden diferenciarse por:

  1. Cantidad de parámetros: Por ejemplo, un constructor recibe 2 parámetros, otro — 3.
  2. Tipos de parámetros: Uno recibe (string, int), otro — (string, decimal).
  3. Orden de los parámetros: (string, int) y (int, string) — son firmas diferentes.

La regla más importante: el compilador distingue los constructores (y cualquier método) por su firma. La firma incluye el nombre del constructor (o método) y la lista de sus parámetros (cantidad, tipos y orden). Los modificadores de acceso (public, private) y, para métodos normales, el tipo de retorno, no forman parte de la firma. Pero los constructores no tienen tipo de retorno, y el nombre siempre coincide con el de la clase.

2. Sobrecarga de constructores: sintaxis y ejemplo


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

    // Constructor sin parámetros
    public Cat()
    {
        Name = "Gato sin nombre";
        Color = "Gris";
    }

    // Constructor con un parámetro
    public Cat(string name)
    {
        Name = name;
        Color = "Gris";
    }

    // Constructor con dos parámetros
    public Cat(string name, string color)
    {
        Name = name;
        Color = color;
    }
}

Uso:

Cat cat1 = new Cat(); // "Gato sin nombre", "Gris"
Cat cat2 = new Cat("Murzik"); // "Murzik", "Gris"
Cat cat3 = new Cat("Ryzhik", "Naranja"); // "Ryzhik", "Naranja"

Si al crear el objeto pones parámetros, C# "adivina" el constructor correcto por la cantidad y tipo de los mismos.

¡Esto es súper cómodo! El usuario de tu clase no tiene que poner parámetros que no conoce: si solo quiere un gato — usa el constructor sin parámetros, si sabe el nombre — usa otro, y así. Si quiere controlar el color — usa la tercera opción.

3. ¿Cómo funciona la llamada a constructores sobrecargados?

C# elige el constructor correcto automáticamente en tiempo de compilación, según el tipo y cantidad de argumentos que le pases. Es difícil equivocarse — si te lías, el compilador te lo dice clarito.

Vamos a añadir un constructor con un parámetro entero:

public Cat(int age)
{
    Name = "Gato sin nombre";
    Color = "Gris";
    // Código extra para la edad
}

Ahora podemos crear también un "gatito por edad":

Cat oldCat = new Cat(5); // Llama al constructor Cat(int age)
Llamada al constructor ¿Cuál se llama?
new Cat()
Sin parámetros
new Cat("cat4")
Con un parámetro string
new Cat("Ryzhik", "Naranja")
Con dos parámetros string
new Cat(10)
Con un parámetro int

4. Llamadas internas de constructores: palabra clave this

A veces, diferentes constructores hacen cosas parecidas (o iguales). Para no copiar código, puedes "llamar a un constructor desde otro". Para eso se usa la palabra clave this.


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

    public Cat() : this("Gato sin nombre")
    {
        // Este constructor llama a Cat(string name)
    }

    public Cat(string name) : this(name, "Gris")
    {
        // Este constructor llama a Cat(string name, string color)
    }

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

Al final:

  • new Cat() llama a Cat(string name), que llama a Cat(string name, string color).
  • Todos los "caminos llevan a Roma": o sea, toda la inicialización está en un solo constructor "principal".

A este enfoque se le llama constructor chaining (encadenamiento de constructores).

5. Ejemplos de la vida real

¡Vamos a crear una clase héroe (Hero) para un juego, que tiene nombre y nivel! Así la escribiríamos:

Con un solo constructor:

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

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

¡Y ahora vamos a dejar que se cree de varias formas!

Varios constructores:

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

    // Si no se indica nada, el héroe será "Sin nombre" de nivel 1
    public Hero() : this("Sin nombre", 1)
    {
    }

    // Si solo sabemos el nombre, nivel por defecto — 1
    public Hero(string name) : this(name, 1)
    {
    }

    // El constructor principal con dos parámetros
    public Hero(string name, int level)
    {
        Name = name;
        Level = level;
    }
}

Ahora puedes crear héroes de varias formas:

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

6. Detalles de implementación: trampas ocultas y matices

Primero: el compilador no crea un constructor "vacío" por defecto si tú declaras al menos otro constructor. Así que, si escribiste tu constructor con parámetros pero olvidaste añadir el sin parámetros, esta llamada:

Hero h = new Hero(); // ¡Error si no hay constructor sin parámetros!
dará error de compilación.

Segundo: si en el chaining de constructores llamas al que no toca, puedes romper la lógica de inicialización. Es importante ser consistente: mejor que todo el trabajo real esté en el constructor más completo, y los demás solo pasen datos allí con this(...).

Tercero: si los parámetros solo se diferencian por tipo (por ejemplo, Cat(string s) y Cat(object o)), puedes liarla al llamar al constructor con un argumento null. El compilador no siempre sabe cuál quieres usar.

7. Sobrecarga e inicialización de campos

A menudo en una clase hay campos que sí o sí hay que poner. La sobrecarga de constructores ayuda a hacerlo cómodo, pero tú decides qué valores por defecto tienen sentido para tu clase.

Ejemplo con comprobación:

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

    // Libro por defecto — "Sin título", año 2000
    public Book() : this("Sin título", 2000)
    {
    }
    
    public Book(string title) : this(title, 2000)
    {
    }

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

8. Sobrecarga con diferentes conjuntos de parámetros

Puedes encontrarte clases con decenas de constructores. No siempre es buena arquitectura (a veces es mejor usar métodos de configuración o el patrón "builder"), pero para objetos de usuario, modelos, DTO — es una opción válida.

Ejemplo: clase "Mascota", donde puedes indicar todas las características, o solo las más necesarias.

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

    // Constructor por defecto
    public Pet() : this("NoName", 0, "Cat", false) { }

    // Mínima información
    public Pet(string name, string type) : this(name, 0, type, false) { }

    // Constructor completo
    public Pet(string name, int age, string type, bool isVaccinated)
    {
        Name = name;
        Age = age;
        Type = type;
        IsVaccinated = isVaccinated;
    }
}
Diferencia entre sobrecarga de método y de constructor
Método normal Constructor (incluyendo sobrecargado)
Se puede llamar en cualquier momento Solo se llama al crear el objeto (new)
Puedes devolver valores de cualquier tipo Nunca devuelve valor (no se indica tipo)
El nombre del método es cualquiera, normalmente un verbo El nombre siempre es igual al de la clase
Se puede sobrecargar por parámetros También se sobrecarga por parámetros
2
Tarea
C# SELF, nivel 16, lección 4
Bloqueada
Creación de una clase con sobrecarga de constructores
Creación de una clase con sobrecarga de constructores
2
Tarea
C# SELF, nivel 16, lección 4
Bloqueada
Llamada al constructor usando `this`
Llamada al constructor usando `this`
1
Cuestionario/control
Concepto de clase y objeto, nivel 16, lección 4
No disponible
Concepto de clase y objeto
Clases y constructores
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION