que-son-metodos-variables-estaticos-en-programacion

Qué son las variables y métodos estáticos

Las variables y métodos estáticos son aquellos que pertenecen a la clase en sí misma, en lugar de a instancias individuales de la clase.

Esto significa que existe una única copia de cada variable o método estático, compartida por todas las instancias de esa clase.

Por poner un ejemplo, si tuvieras una clase Persona y cada instancia tuviera su libro donde tiene sus propios datos, las variables y métodos estáticos serían una gran pizarra compartida de la que todos pueden leer y escribir.

poo-variables-metodos-estaticos

Todas las personas comparten la pizarra común

Los métodos estáticos suponen una aproximación a la programación procedural, sin salirse (mucho) de los paradigmas de la programación orientada a objetos. Mientras, las variables estáticas son algo similar a “variables globales”.

Además resultan ligeramente más cómodos de usar que los de instancia, porque no requieren crear la instancia antes de usarlos.

Variables y métodos de estáticos

Variables de estáticos

Las variables estáticas pertenecen a la clase. Esto significa que hay una única copia de la variable, compartida por todas las instancias de la clase.

Cualquier método, tanto los de instancia como los estáticos, pueden potencialmente acceder a las variables (siempre que los modificadores de acceso se lo permitan).

Las variables estáticas se pueden utilizar para almacenar datos que deben ser accesibles para todas las instancias, para mantener un estado global, o constantes.

Métodos de estáticos

Los métodos estáticos son funciones que pertenecen a la clase y no a una instancia de la clase.

Estos métodos no pueden acceder a variables ni métodos de instancia directamente, porque para ellos no existen las instancias. Sin embargo, si pueden acceder a otras variables y métodos estáticos.

Caso práctico

Volvamos al caso práctico de la clase Persona que teníamos al ver las variables y métodos de instancia. En esta ocasión, hemos añadido una variable estática Contador y un método estático ejemplo IncrementarContador().

Persona
  • stringNombre
  • stringDni
  • static intContador
  • static voidIncrementarContador()

En primer lugar, desde cualquier parte del código puedo acceder a las variables y métodos estáticos. Es decir, es posible hacer esto desde cualquier sitio,

Persona.Contador = 12;
Persona.IncrementarContador();

Por supuesto, “desde cualquier sitio” implica que todas las instancias pueden acceder igualmente a las variables. Incluso en la propia definición de la clase.

De hecho, uno de los ejemplo típico de variables y métodos estáticos, añadir un contador que cuente las instancias que generamos de una clase. (Al final veremos que esto no es una buena idea 🙅‍♂️, salvo para hacer un ejemplo)

Si quisiéramos hacer eso, simplemente en el constructor de Persona incrementaríamos la variable estática Contador.

class Persona 
{
	Persona()
	{
		Persona.Contador++;

		// tambien podriamos llamar al metodo estatico
		//Persona.IncrementarContador();
	}
}

Que como digo como idea no es la mejor del mundo, pero ilustra bien como podemos usar las variables y métodos estáticos desde cualquier parte del código.

Ejemplos en distintos lenguajes

Finalmente, vamos a ver cómo distintos lenguajes implementan el concepto de variables y métodos estáticos.

En C#, las variables y métodos estáticos se definen utilizando la palabra clave static.

public class Contador
{
    // Variable estática
    public static int Contador;

    // Método estático
    public static void IncrementarContador()
    {
        Contador++;
    }
}

// Uso
Contador.IncrementarContador();
Console.WriteLine(Contador.Contador);

En C++, las variables y métodos estáticos se definen utilizando la palabra clave static.

#include <iostream>

class Contador {
public:
    // Variable estática
    static int Contador;

    // Método estático
    static void IncrementarContador() {
        Contador++;
    }
};

// Definición de la variable estática
int Contador::Contador = 0;

// Uso
int main() {
    Contador::IncrementarContador();
    std::cout << Contador::Contador << std::endl;
    return 0;
}

En JavaScript, las variables y métodos estáticos se definen utilizando la palabra clave static. Estas variables y métodos pertenecen a la clase en lugar de a las instancias individuales de la clase.

class Contador {
    // Variable estática
    static contador = 0;

    // Método estático
    static incrementarContador() {
        Contador.contador++;
    }
}

// Uso
Contador.incrementarContador();
console.log(Contador.contador);

En TypeScript, las variables y métodos estáticos se definen utilizando la palabra clave static.

class Contador {
    // Variable estática
    static contador: number = 0;

    // Método estático
    static incrementarContador(): void {
        Contador.contador++;
    }
}

// Uso
Contador.incrementarContador();
console.log(Contador.contador);

En Python, las variables y métodos estáticos se pueden simular utilizando decoradores @classmethod y variables de clase.

class Contador:
    # Variable estática
    contador = 0

    # Método estático
    @classmethod
    def incrementar_contador(cls):
        cls.contador += 1

# Uso
Contador.incrementar_contador()
print(Contador.contador)

Buenas prácticas Consejos

La pregunta del millón con los métodos estáticos es ¿Cuándo uso un método estático y cuando no? Y a lo largo de vuestra vida ya os digo que vais a cambiar varias veces entre amarlos a odiarlos😘.

En principio, mi consejo, es que evitéis los métodos y variables estáticos siempre que sea posible. El motivo principal es que no los puedes sobreescribir, ni los puede reemplazar fácilmente ni… básicamente no te dan casi nada de juego.

Una vez que tu código se “engancha” a un método estático, estás atado muy atado a él. Eso significa que me darán problemas de mantenibilidad en el futuro, de testeo, para hacer mocks… me van a dar problemas de todo.

MiClase.DoSomething();  // una vez que metas eso, te lo comes para siempre

Además, la mayoría de veces no tiene sentido usarlos. En el ejemplo que hemos puesto, que es el típico que se usa, de un contador que cuenta el número de instancias de Persona creadas… bueno eso en la vida real es una guarrada.

Si vas a hacer algo así, lo lógico es que tengas un objeto superior PersonaManager o GrupoPersona, o lo que sea, que contenta esa información que normalmente en los ejemplos se usa para ilustrar las variables y métodos estáticos.

public class PersonaManager
{
	public int Counter;
	
	public Persona GeneratePersona() {
		//.. lo que sea 
	}
}

Sin embargo, tampoco hay que negar que los métodos estáticos aportan sencillez a los programas. Por ejemplo, imagina que haces una librería que descarga videos de Internet. Es posible que un método estático sea más sencillo de usar.

// es más fácil de usar esto
VideoDownloader.Download("url_al_video");

// que esto
var videoDownloader = new VidewDownloader();
videoDownloader.Download("url_al_video");

En definitiva, mi consejo es evitar los métodos estáticos todo lo posible. Sólo sí tienen sentido en el propósito original, que son funciones muy aisladas, y que no requieren variables o información propia.

El ejemplo típico es una función con funciones matemáticas, que simplemente quieres tener las funciones agrupadas, pero básicamente sigue siendo programación procedural. Ahí, tiene sentido que sean estáticas.

O, cuando quieras ofrecer una forma más sencilla para el desarrollador de usar una librería. Y normalmente siempre como atajo de un método alternativo, que ofrece más funciones.