que-es-un-constructor-y-destructor-en-programacion

What are constructors and destructors

  • 7 min

A Constructor is a special type of method used to initialize new instances of a class.

That is, when we create an instance of a class, the Constructor is a method that is executed automatically during creation (usually to set the initial state of the object).

programacion-constructor

The constructor, building your objects

Why might we want to execute a method when creating an object? Well, generally to:

  • Initialize variables and internal state
  • Perform certain validations
  • Or to do absolutely nothing 🤷

Because yes, many times what we will want to do is absolutely nothing. Not all objects need us to do “something” in their constructor (in fact, most don’t need it).

Finally, most languages allow defining multiple constructors for a class, each with different parameters. This is called constructor overloading.

Examples of constructors in different languages

Generally, the Constructor is a method that:

  • Name: Usually, it has the same name as the class it belongs to.
  • Parameters: It receives parameters
  • No return: Unlike other methods, constructors do not have a return type, not even void.

Let’s see what a constructor looks like in different programming languages, and how we would use it to create instances of a Person class.

public class Persona {
    public string nombre;
    public int edad;
    
    // Constructor
    public Persona(string nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    public void Presentarse() {
        Console.WriteLine($"Hola, mi nombre es {nombre} y tengo {edad} años.");
    }
}

// Crear una instancia de la clase Persona
Persona personaLuis = new Persona("Luis", 30);
personaLuis.Presentarse();

// Crear otra instancia de la clase Persona
Persona personaMaria = new Persona("Maria", 20);
personaMaria.Presentarse();
Copied!
class Persona {
public:
    string nombre;
    int edad;

    // Constructor
    Persona(string nombre, int edad) {
        this->nombre = nombre;
        this->edad = edad;
    }

    void presentarse() {
        cout << "Hola, mi nombre es " << nombre << " y tengo " << edad << " años." << endl;
    }
};

// Crear una instancia de la clase Persona
Persona personaLuis("Luis", 30);
personaLuis.presentarse();

// Crear otra instancia de la clase Persona
Persona personaMaria("Maria", 20);
personaMaria.presentarse();
Copied!
class Persona {
    constructor(nombre, edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    presentarse() {
        console.log(`Hola, mi nombre es ${this.nombre} y tengo ${this.edad} años.`);
    }
}

// Crear una instancia de la clase Persona
const personaLuis = new Persona("Luis", 30);
personaLuis.presentarse();

// Crear otra instancia de la clase Persona
const personaMaria = new Persona("Maria", 20);
personaMaria.presentarse();
Copied!
class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def presentarse(self):
        print(f"Hola, mi nombre es {self.nombre} y tengo {self.edad} años.")

# Crear una instancia de la clase Persona
personaLuis = Persona("Luis", 30)
personaLuis.presentarse()

# Crear otra instancia de la clase Persona
personaMaria = Persona("Maria", 20)
personaMaria.presentarse()
Copied!

In the previous examples, we see the constructor of the Persona class, and it initializes the instance variables nombre and edad.

On the other hand, we see how the constructor is used when we create a class instance for the case of Luis aged 30, and Maria aged 20.

Destructors

Just as constructors handle initialization, Destructors (or finalizers) are special methods that are executed when an object is destroyed or released.

Destructors are used to perform any necessary cleanup before the object is removed from memory (in general, mainly to release resources, such as closing files or database connections).

Examples of destructors in different languages

Let’s see how to create Destructors or finalizers in different programming languages.

In C#, destructors (~Persona) are called automatically when the object is about to be destroyed, allowing resource release.

public class Persona {
    public string nombre;
    public int edad;

    // Constructor
    public Persona(string nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    // Destructor
    ~Persona() {
        Console.WriteLine($"El objeto Persona {nombre} ha sido destruido.");
    }
}
Copied!

Similarly, in C++ the destructor (~Persona) is also declared in a similar way.

class Persona {
public:
    string nombre;
    int edad;

    // Constructor
    Persona(string nombre, int edad) {
        this->nombre = nombre;
        this->edad = edad;
    }

    // Destructor
    ~Persona() {
        cout << "El objeto Persona " << nombre << " ha sido destruido." << endl;
    }
};
Copied!

In JavaScript, there is no concept of destructors. However, we can use certain patterns to clean up resources if necessary.

class Persona {
    constructor(nombre, edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    presentarse() {
        console.log(`Hola, mi nombre es ${this.nombre} y tengo ${this.edad} años.`);
    }

    // Method to manually release resources
    liberarRecursos() {
        console.log(`Recursos de ${this.nombre} han sido liberados.`);
    }
}

// Example of use
const personaLuis = new Persona("Luis", 30);
personaLuis.presentarse();
personaLuis.liberarRecursos();
Copied!

In Python, the destructor (__del__) is called when the object is collected by the garbage collector, or when we force its destruction using del.

class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def __del__(self):
        print(f"El objeto Persona {self.nombre} ha sido destruido.")

    def presentarse(self):
        print(f"Hola, mi nombre es {self.nombre} y tengo {self.edad} años.")

# Example of use
personaLuis = Persona("Luis", 30)
personaLuis.presentarse()
del personaLuis  # Force the destruction of the object
Copied!

Best Practices tips

When to use a constructor

Throughout your life as a programmer, you will probably go through a love-hate relationship with constructors. Especially regarding when you have to use a Constructor, and when it’s better to use other mechanisms.

You’ll probably start using them timidly at first. Then you’ll be tempted to use them for everything. And in the end, you’ll start not using them at all, preferring other ways to initialize objects like the Factory Pattern.

In any case, the less you use constructors, the better (controversial 😮). It’s preferable to have simple objects, containing as little logic as possible, and using them as data containers.

For me, when does it make sense to use a constructor? When you are initializing variables that the object needs to function and without that variable it doesn’t even make sense for it to exist.

For example, imagine you have a Repository object, whose function is to save data to a database. For that, it needs a connection to a database.

public class Repository
{
	DbConnection _connection;
	
	Repository(DbConnection connection)
	{
		_connection = connection;
	}

	// more methods
}
Copied!

It’s not debatable that Repository has a connection. Without it, any call to that object will result in an error. Literally, the Repository object makes no sense to exist without a connection.

In that case, it’s logical for Repository to receive the connection in the constructor. Because it’s the minimum necessary for it to work.

But, what about a Car object? We might think that the minimum a Car needs is its license plate (license plate).

public class Coche
{
	string _matricula;
	
	Coche(string matricula)
	{
		_matricula = matricula;
	}
}
Copied!

But, what if I can have cars in a dealership that don’t have a license plate yet? Do we take the chassis number? And if what I’m programming is a Parking lot, and I don’t have chassis numbers?

That is, there is no single answer. What is necessary, and what should go in the constructor, depends on your object model.

That is part of the process of designing the object model of your program. As advice, don’t use a constructor except in those cases where you are very clear about it.

On the other hand, when you need / decide to use a constructor, always follow these guidelines:

  • As simple as possible
  • It should never be a long process (like reading from a database, from a file, etc)
  • Make them as independent as possible from other classes

When to use a destructor

For their part, Destructors are less open to debate. If during the use of a class you are employing a resource, you must ensure it is released when the instance is destroyed. There is less doubt here about when to use it, this should always be done.