Métodos y atributos static en Programación Orientada a Objetos

  • Por
Definición y ejemplos de elementos o miembros static, los métodos y atributos de clase o estáticos en la programación orientada a objetos.

En el Manual de la Teoría de la programación orientada a objetos estamos revisando diversos conceptos y prácticas comúnmente usadas en este paradigma de la programación. Ahora le toca el turno a "static".

Seguramente lo has visto en alguna ocasión en algún código, pues se trata de una práctica bastante común. Con "static", un modificador que podemos aplicar en la definición de métodos y atributos de las clases, podemos definir estos elementos como pertenecientes a la clase, en lugar de pertenecientes a la instancia. A lo largo de este artículo queremos explicar bien qué es esto de los elementos estáticos "static" o también llamados elementos "de clase".

Qué es static

La definición formal de los elementos estáticos (o miembros de clase) nos dice que son aquellos que pertenecen a la clase, en lugar de pertenecer a un objeto en particular. Recuperando concetos básicos de orientación a objetos, sabemos que tenemos:

Clases: definiciones de elementos de un tipo homogéneo.
Objetos: concreción de un ejemplar de una clase.

En las clases defines que tal obteto tendrá tales atributos y tales métodos, sin embargo, para acceder a ellos o darles valores necesitas construir objetos de esa clase. Una casa tendrá un número de puertas para entrar, en la clase tendrás definida que una de las características de la casa es el número de puertas, pero solo concretarás ese número cuando construyas objetos de la clase casa. Un coche tiene un color, pero en la clase solo dices que existirá un color y hasta que no construyas coches no les asignarás un color en concreto. En la clase cuadrado definirás que el cálculo del área es el "lado elevado a dos", pero para calcular el área de un cuadrado necesitas tener un objeto de esa clase y pedirle que te devuelva su área.

Ese es el comportamiento normal de los miembros de clase. Sin embargo, los elementos estáticos o miembros de clase son un poco distintos. Son elementos que existen dentro de la propia clase y para acceder los cuales no necesitamos haber creado ningún objeto de esa clase. Osea, en vez de acceder a través de un objeto, accedemos a través del nombre de la clase.

Ejemplos de situaciones de la vida real donde tendríamos miembros estáticos

De momento así dicho queda un tanto abstracto. Pero antes de ponerse con ejemplos concretos de programación donde hablemos de la utilidad práctica de los miembros estáticos sea bueno tratar de explicar estos conceptos un con situaciones de la vida real.

Por ejemplo, pensemos en los autobuses de tu ciudad. No sé si es el caso, pero generalmente en España todos los autobuses metropolitanos tienen la misma tarifa. Yo podría definir como un atributo de la clase AutobúsMetropolitano su precio. En condiciones normales, para acceder al precio de un autobús necesitaría instanciar un objeto autobús y luego consultar su precio. ¿Es esto práctico? quizás solo quiero saber su precio para salir de casa con dinero suficiente para pagarlo, pero en el caso de un atributo normal necesariamente debería tener instanciado un autobús para preguntar su precio.

Pensemos en el número "Pi". Sabemos que necesitamos ese número para realizar cálculos con circunferencias. Podría tener la clase Circunferencia y definir como atributo el número Pi. Sin embargo, igual necesito ese número para otra cosa, como pasar ángulos de valores de grados a radianes. En ese caso, en condiciones normales sin atributos de clase, necesitaría instanciar cualquier círculo para luego preguntarle por el valor de "Pi". De nuevo, no parece muy práctico.

Nota: Ojo, porque en el caso del número Pi, su valor será siempre constante. Podríamos en esa caso usar constantes si nuestro lenguaje las tiene, pero los atributos estáticos no tienen por qué ser siempre un valor invariable, como es el caso del precio de los AutobusesMetropolitanos, que sube cada año.

Con esos tenemos dos ejemplos de situaciones en las que me pueden venir bien tener atributos "static", o de clase, porque me permitirían consultar esos datos sin necesidad de tener una instancia de un objeto de esa clase.

En cuanto a métodos, pensemos por ejemplo en la clase Fecha. Puedo intentar construir fechas con un día, un mes y un año, pero puede que no necesite una fecha en un momento dado y solo quiera saber si una fecha podría ser válida. En situaciones normales debería intentar construir esa fecha y esperar a ver si el constructor me arroja un error o si la fecha que construye es válida. Quizás sería más cómodo tener un método vinculado a la clase, en el que podría pasarle un mes, un día y un año y que me diga si son válidos o no.

Cómo definir y usar miembros estáticos

Esto ya depende de tu lenguaje de programación. Generalmente se usa el modificador "static" para definir los miembros de clase, al menos así se hace en Java o PHP, C#, pero podrian existir otros métodos en otros lenguajes.

Nota: El código que verás a continuación no es de uno u otro lenguaje. No es mi objetivo explicar Java, PHP, C#, etc. sino ver en pseudo-codigo rápidamente una posible implementación de el uso de static. Es parecido a Java, pero le he quitado algunas cosas que dificultan el entendimiento de los ejemplos. Tampoco es PHP, porque no he metido los $ de las variables y el uso del acceso a variables estáticas se hace con el operador :: que me parece muy feo y que complica la lectura y comprensión de los ejemplos. Tendrás que consultar la documentación de tu propio lenguaje para ver cómo se hace en él, aquí lo que quiero que queden claros son los conceptos nada más.

class AutobusMetropolitano {
	public static precio = 1.20;
}

Podrás observar que en la definición de la clase hemos asignado un valor al precio a la hora de declarar ese atributo de clase. Esto es condición indispensable en muchos lenguajes, puesto que si existe ese atributo debería tener un valor antes de instanciar el primer objeto. Osea, no es como los atributos normales, que les podemos asignar valores a través del constructor.

Luego podríamos acceder a esos elementos a través del nombre de la clase, como se puede ver a continuación:

if(1.5 >= AutobusMetropolitado.precio){
	//todo bien
}

Ese código sería en el caso que estés accediendo al atributo estático desde fuera de la clase, pero en muchos lenguajes puedes acceder a esos atributos (o métodos) desde la vista privada de tus clases (código de implantación de la clase) a través de la palabra "self".

class AutobusMetropolitano {
	static precio = 1.20;
	//...

	public function aceptarPago(dinero){
		if (dinero < self.precio){
			return false;
		}
		// ...
	}
}

En el caso de los métodos estáticos la forma de crearlos o usarlos no varía mucho, utilizando el mismo modificador "static" al declarar el método.

class Fecha{
	//... 
public static function valida(ano, mes, dia){
		if(dia >31)
			return false;
		// ...
	}
	//...
}

Ahora para saber si un conjunto de año mes y día es válido podrías invocar al método estático a través del nombre de la clase.

if(Fecha.valida(2014, 2, 29)){
	// es valida
}else{
	// no es valida
}

Como en el caso de los atributos de clase, también podrías acceder a métodos de clase con la palabra "self" si estás dentro del código de tu clase.

Miembros estáticos son susceptibles de hacer "marranadas"

No quiero dejar este artículo sin aprovechar la oportunidad de explicar que los miembros estáticos deben estár sujetos a un cuidado adicional para no cometer errores de diseño.

En ocasiones se tiende a usar los métodos estáticos para agregar datos a modo de variables globales, que estén presentes en cualquier lugar de la aplicación a partir del nombre de una clase. Esto nos puede acarrear exactamente los mismos problemas que conocemos por el uso de variables globales en general.

En cuanto a métodos estáticos a veces se usan las clases como simples contenedores de unión de diferentes métodos estáticos. Por ejemplo la clase Math en Javascript, o incluso Java, que tiene simplemente una serie de métodos de clase. Usarlos así, creando métodos estáticos en la clase, sin agregar más valor a la clase a través de métodos o atributos "normales" es caer en prácticas similares a las que se vienen usando en la programación estructurada. Dicho de otra manera, es usar la Programación Orientada a Objetos sin aprovechar los beneficios que nos aporta.

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

Paulo Hermida

14/11/2014
Variables globales
Esto de las variables estáticas me suena un poco a variables globales. ¿Cuál es la diferencia?

midesweb

14/11/2014
¿Globales?
Yo entiendo otra cosa por variables globales. Básicamente la diferencia es el contexto.
Una variable global tiene el contexto de todo el programa, en cualquier lugar del código de la aplicación existe y puede ser accesible. Vamos, podríamos decir que no tiene contexto.
En un atributo estático de una clase ya tenemos un contexto, es esa misma clase. No es una variable suelta que puedes acceder desde cualquier parte, sino una variable asociada en este caso al nombre de la clase. Es cierto que esa variable es accesible desde cualquier parte de la aplicación donde se conozca a esa clase, pero al menos su existencia ya está condicionada a la existencia de la clase y para acceder a ella tenemos que entrar en el espacio de nombres de esa clase.
Lo que es verdad y eso se comentó en el artículo, es que los atributos estáticos, o los métodos "static", son susceptibles de hacer cosas no muy elegantes. Si lo que quieres es crear una propiedad estática para que esté disponible en cualquier lugar, pues es verdad que estás creando algo parecido a una variable global. Un atributo estático debe estar correctamente analizado y debe haber un motivo claro por el que se crea.

Joan Delgado

17/11/2014
Consumo de memoria
Instanciar un objeto implica utilizar un espacio del heap para su creacion, sucede algo similar si yo llamo una variable estática de una clase?

Joseba

20/11/2014
Heap
No ocupa espacio, solo el intrínseco a su creación.