Programar (también) te hace (o al menos te ayuda a ser un poco más) responsable. Parte I .
Todos conocemos esa frase que se le atribuye al tío Ben en el universo de Spideman (MR):
Un gran poder conlleva una gran responsabilidad.
Si rascamos un poco en la historia veremos que, es una frase que tiene unos pocos cuantos más de años de existencia; aun así, creo que para todos nos es más amigable pensar que es una frase aportada por la cultura pop y los comics y que, por esta frase no tenemos nada que envidiarle a los antiguos griegos y sus bonitas frases éticas :P
Inicio con este post ya que, recién vi la película de "El multiverso de Spiderman" y, creo que no debí hacerlo en viernes, ya que, estuve todo un fin de semana reflexionando muchas cosas.
Cómo sea, una de las tantas reflexiones fue que, cuando comencé a programar con java 1.2 (llamada Java 2, hace ya muchos ayeres) me causaba conflicto el hecho de que, una vez que una clase compilaba bien, dejaba de hacerlo simplemente por un pequeño cambio que cumplía con toda la sintaxis que exigía el lenguaje.
Y, me refiero por supuesto a este tema que todos los que inician a programar con java se encuentran: el constructor por default con cero parámetros.
Muchos lenguajes orientados a objetos tienen un comportamiento similar al de Java respecto a los constructores por defecto. Este diseño proporciona claridad y control sobre la inicialización de objetos, asegurando que los desarrolladores definan explícitamente cómo deben ser inicializadas sus clases cuando se requiere una lógica específica de construcción. Este post es sólo una reflexión personal sobre esto y no pretende cuestionar de fondo el diseño del lenguaje.
Imaginemos ......
Que tengo las siguientes clases:
Una clase llamada MyClase.
package com.rugi.javaconstructor;
//MyClase
public class MyClase {
//completamente vacía
}
Yo puedo hacer lo siguiente, usar MyClase en otra clase llamada JavaConstructor y, usar MyClase:
package com.rugi.javaconstructor;
public class JavaConstructor {
public static void main(String[] args) {
MyClase clase1 = new MyClase();
System.out.println(clase1);
}
}
(Si ambas clases están en un mismo paquete, la ejecución de la clase anterior dará como resultado algo parecido a esto):
com.rugi.javaconstructor.MyClase@1eb44e46
(No discutiremos ahorita porqué salió ese mensaje todo raro, ese es otro tema)
MyClase, se encuentra completamente vacía, no tiene nada de código y, aun así, el compilador me asiste con el constructor por default: el constructor por default con cero parámetros:
MyClase()
Realmente el compilador me está asistiendo con algo parecido a esto:
public MyClase() {
// Constructor por default con cero parámetros
}
Los diseñadores del lenguaje quizá dijeron: ayudémos a esta pobre alma, apenas está empezando a programar, quizá no tenga idea de programación orientada a objetos (POO), incluso quizá apenas y sabe escribir con el teclado pero: ha decidido dar el primer paso y está creando su primera clase: ¡¡¡Qué decidido, qué digno, qué estoico!!!
Bueno, quizá no dijeron todo eso, pero, creo que queda claro lo que quisieron hacer.
Hasta acá, podemos hacer un examen de consciencia y reconocer que esto, no sólo es una asistencia para los neófitos en el lenguaje, sino que ademas, ayuda a que el lenguaje se mantenga simple y flexible incluso para los que llevamos varios años usando el lenguaje.
Pero, ¿Dónde está lo simple y flexible?
Quizá estoy apenas prototipando mi jerarquía de clases y, en realidad pienso que MyClase debe tener una clase hija.
Algo así:
package com.rugi.javaconstructor;
public class MyClaseEspecial extends MyClase {
}
Si modifico la clase JavaConstructor:
Recomendado por LinkedIn
package com.rugi.javaconstructor;
public class JavaConstructor {
public static void main(String[] args) {
MyClase clase1 = new MyClase();
MyClaseEspecial claseEspecial = new MyClaseEspecial();
System.out.println(clase1);
System.out.println(claseEspecial);
}
}
Todo seguirá compilando sin problemas y al ejecutar veremos algo como esto:
com.rugi.javaconstructor.MyClase@6504e3b2
com.rugi.javaconstructor.MyClaseEspecial@379619aa
Hasta acá todo muy bonito.
Pero ¿Qué pasa si decido ponerle a mi clase un constructor que reciba por ejemplo un número entero?.
package com.rugi.javaconstructor;
public class MyClase {
public MyClase(int valor){
}
}
Sólo agregué un constructor, ¿Estamos de acuerdo? (sí, responde la audiencia).
En cuanto grabemos ese archivo, si intentamos compilar encontrarémos dos mensajes de error por parte del compilador:
Para la clase JavaConstructor:
com/rugi/javaconstructor/JavaConstructor.java:[14,26] constructor MyClase in class com.rugi.javaconstructor.MyClase cannot be applied to given types;
required: int
found: no arguments
reason: actual and formal argument lists differ in length
El compilador nos dice más o menos lo siguiente: ¡Hey!, En la clase MyClase solo veo un constructor que recibe 1 int y me estás escribiendo acá uno sin argumentos, y ese no lo conozco. ¿Cómo le hacemos?
Para la clase MyClaseEspecial:
com/rugi/javaconstructor/MyClaseEspecial.java:[7,8] constructor MyClase in class com.rugi.javaconstructor.MyClase cannot be applied to given types;
required: int
found: no arguments
reason: actual and formal argument lists differ in length
Lo mismo.
Cuando alguien comienza a programar con java lo primero que se pregunta al encontrarse en esta encrucijada es:
¿Y dónde quedó el constructor que ya tenía? , ¡¡¡Árbitro!! ese código ya compilaba, devuelvan las entradas, ¿Y ahora cómo avanzo?
En realidad, el compilador ha decidido que ya somos unos adultos, y ya no requerimos de su asistencia.
Al momento de poner nosotros al menos un constructor, el compilador deja de asistirnos con el constructor por default ... así de cruel, como la vida misma. :P
¿Qué tenemos que hacer para resolver esto?, dado que ya somos unos adultos, debemos escribir explicitamente este constructor por default con cero parámetros.
package com.rugi.javaconstructor;
public class MyClase {
//definimos explicitamente el constructor por default con cero parámetros.
public MyClase(){
}
public MyClase(int valor){
}
}
Y con eso, todo vuelve a la normalidad. :)
De esta forma, al quitarnos el constructor por default con cero parámetros, el compilador se asegura que estamos tomando control completo de esa clase (y eventualmente de toda la jerarquía a la que pertenece) y nuestro código debería ser más sencillo de leer, más consistente y controlado.
¿Qué te parece este feature del diseño del lenguaje?
Seguro hay otras particulares del lenguaje java mucho menos simples como esta que pueden usarse para encaminar este discurso hacia la responsabilidad de nuestras acciones en general y de nuestro código en particular, sin duda también otros lenguajes también las tienen; pero quise iniciar con esta breve reflexión que traía atorada desde inicios del 2000. ;)
---
WORA pro omnibus!.