Language: EN

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

What are constructors and destructors

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 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: Generally, it has the same name as the class to which it belongs.
  • Parameters: Receives the parameters
  • No Return Type: Unlike other methods, constructors do not have a return type, not even void.

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

public class Person {
    public string name;
    public int age;
    
    // Constructor
    public Person(string name, int age) {
        this.name = name;
        this.age = age;
    }

    public void Introduce() {
        Console.WriteLine($"Hello, my name is {name} and I'm {age} years old.");
    }
}

// Create an instance of the Person class
Person personLuis = new Person("Luis", 30);
personLuis.Introduce();

// Create another instance of the Person class
Person personMaria = new Person("Maria", 20);
personMaria.Introduce();
class Person {
public:
    string name;
    int age;

    // Constructor
    Person(string name, int age) {
        this->name = name;
        this->age = age;
    }

    void Introduce() {
        cout << "Hello, my name is " << name << " and I'm " << age << " years old." << endl;
    }
};

// Create an instance of the Person class
Person personLuis("Luis", 30);
personLuis.Introduce();

// Create another instance of the Person class
Person personMaria("Maria", 20);
personMaria.Introduce();
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    Introduce() {
        console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
    }
}

// Create an instance of the Person class
const personLuis = new Person("Luis", 30);
personLuis.Introduce();

// Create another instance of the Person class
const personMaria = new Person("Maria", 20);
personMaria.Introduce();
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def Introduce(self):
        print(f"Hello, my name is {self.name} and I'm {self.age} years old.")

# Create an instance of the Person class
personLuis = Person("Luis", 30)
personLuis.Introduce()

# Create another instance of the Person class
personMaria = Person("Maria", 20)
personMaria.Introduce()

In the previous examples, we see that the constructor of the Person class initializes the instance variables name and age.

On the other hand, we see how the constructor is used when we create an instance of a class in the case of Luis, who is 30 years old, and Maria, who is 20 years old.

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 (~Person) are automatically called when the object is going to be destroyed, allowing resource release.

public class Person {
    public string name;
    public int age;

    // Constructor
    public Person(string name, int age) {
        this.name = name;
        this.age = age;
    }

    // Destructor
    ~Person() {
        Console.WriteLine($"The Person object {name} has been destroyed.");
    }
}

Similarly, in C++ the destructor (~Person) is also declared similarly.

class Person {
public:
    string name;
    int age;

    // Constructor
    Person(string name, int age) {
        this->name = name;
        this->age = age;
    }

    // Destructor
    ~Person() {
        cout << "The Person object " << name << " has been destroyed." << endl;
    }
};

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

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    Introduce() {
        console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
    }

    // Method to manually release resources
    releaseResources() {
        console.log(`Resources of ${this.name} have been released.`);
    }
}

// Usage example
const personLuis = new Person("Luis", 30);
personLuis.Introduce();
personLuis.releaseResources();

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 Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __del__(self):
        print(f"The Person object {self.name} has been destroyed.")

    def Introduce(self):
        print(f"Hello, my name is {self.name} and I'm {self.age} years old.")

# Usage example
personLuis = Person("Luis", 30)
personLuis.Introduce()
del personLuis  # Force object destruction

Cleaning Tips Tips

Throughout your life as a programmer, you will probably go through a love-hate relationship with constructors. Above all in terms of when you have to use a Constructor, and when it is best to use other mechanisms.

You will probably use them timidly at first. Then you will be tempted to use them for everything. And in the end you will start not using them at all, and prefer other ways to initialize objects such as the Factory Pattern.

In any case, the less you use constructors the better (controversial 😮). It is preferable to have simple objects, containing the least possible logic, and use 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 make sense for it to exist.

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

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

	// more methods
}

It is not debatable for Repository to have a connection. Without it, any call to that object will result in an error. Literally, the Repository object doesn’t make sense to exist without a connection.

In that case, it is logical for Repository to receive the connection in the constructor. Because it is 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

public class Car
{
	string _licensePlate;
	
	Car(string licensePlate)
	{
		_licensePlate = licensePlate;
	}
}

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

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

This is part of the process of designing the object model of your program. As a tip, don’t use a constructor unless in those cases that you are very clear about it.

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

  • As simple as possible
  • It should never be a long process (like reading from a database, from a file, etc)
  • They should be as independent as possible from the rest of the classes

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