Posted on • Edited on
C#: IDE, por favor, no me "ayudes" más... (II)
Otro caso en el que los subrayados rojos aparecen demasiado pronto, es el siguiente. Recuerda la claseCalificacion, que guardaba una referencia a una asignatura y una nota. Necesitamos la claseCalificacionTeoriaPractica, que acepta también una referencia a una asignatura y, en este caso, dos notas, una de teoría y otra de prácticas.
Así que creamos la claseCalificacionTeoriaPractica hereda de la claseCalificacion. Empezamos a teclear y...
Pues nada... ya nos aparece subrayada en rojo... en fin... hacemos de tripas corazón y continuamos para escribir el constructor. Y también nos lo subraya en rojo.
Hemos "aguantado" hasta ahora, pero llega el momento de poner el cursor del ratón encima de la parte subrayada y ver qué tripa se le ha roto... quiero decir, qué error tiene nuestro código.
El problema es que un estudiante habría entrado ya en modo frenético quita-el-subrayado-o-muere, y se encuentra con que se le ofrecen dos posibilidades:
Context actions |
---|
Add 'base' initializer |
Add default constructor in class 'Calificacion' |
... |
Que podemos resumir en cuanto a significado como sigue:
Mecanismo | Significado |
---|---|
Inicializador 'base' | Ejecuta el constructor de la clase base con los parámetros dados |
Constructor por defecto | Constructor sin parámetros |
La primera añade el texto: base() a nuestra declaración, de forma que tendríamos:
classCalificacionTeoriaPracticas:Calificacion{publicCalificacionTeoriaPracticas(Asignaturaasignatura,decimalteoria,decimalpractica):base(){}}
Esto nosoluciona el problema, sino que ahora el subrayado se ha movido a la última parte (esebase()), que el IDE nos ha añadido. Si lo que queremos es eliminar el subrayado rojo, no hemos mejorado gran cosa. De acuerdo, escojamos la segunda opción. Y... ¡bingo! ¡Todos los subrayados rojos han desaparecido! ¡Esta claro que esta es la opción correcta!
El problema es que no, no es la opción correcta. De hecho, dudo que sea la opción correcta en el 99% de los casos, lo que me hace preguntarme por qué se creo esa posibilidad. Quizás porque era "fácil" de añadir... no lo sé.
De acuerdo, continuamos con el programa:
classCalificacionTeoriaPracticas:Calificacion{publicCalificacionTeoriaPracticas(Asignaturaasignatura,decimalteoria,decimalpractica){this.Asignatura=asignatura;this.Nota=(teoria+practica)/2;}}
¡El problema ha vuelto! ¡El contenido del constructor, las dos líneas están subrayadas en rojo!
De acuerdo, el problema es que las notas están marcadas como de solo lectura. Puedo modificarlas para que puedan ser escritas desde clases derivadas, conprotect.
publicclassCalificacion:IComparable<Calificacion>{// más cosas...publicdecimalNota{get;protectedset;}publicAsignaturaAsignatura{get;protectedset;}}
Ufff... hecho. Y no he tenido que crear las propiedades como de escritura pública. Bien. Utilicemos el nuevo código.
varasig=newAsignatura("Matracas");varnota=newCalificacion(asig,7.8m);varnota2=newCalificacionTeoriaPracticas(asig,7m,6m);Console.WriteLine($"{nota.Asignatura.Nombre}:{nota.Nota}");Console.WriteLine($"{nota2.Asignatura.Nombre}:{nota2.Nota}");
Así que compilo, ejecuto, y... sucede algo raro.
Unhandled exception. System.NotImplementedException: The method or operation is not implemented.
¡¿Pero qué?! ¿El método no está implementado? Veamos el código deCalificacionTeoriaPractica... nada raro... ¿y el deCalificacion? Bueno, apenas está cambiado, pero... por si acaso.
publicclassCalificacion{publicCalificacion(Asignaturaasigantura,decimalnota){this.Asignatura=asigantura;this.Nota=nota;}protectedCalificacion(){thrownewNotImplementedException();}// ...}
¿Se refiería a esto el IDE cuando decía que iba a añadir un constructor por defecto? A ver, esprotected, pero... de todas formas, ¿qué puedo poner ahí? ¿Nada?
publicclassCalificacion{publicCalificacion(Asignaturaasigantura,decimalnota){this.Asignatura=asigantura;this.Nota=nota;}protectedCalificacion(){}// ...}
Veamos, el problema ha desaparecido. Una compilación y ejecución más tarde...
Matracas: 7,8Matracas: 6,5
¡Bien, funciona!
Pero... ¿realmente hemos arreglado algo? Repasemos: hemos modificado las propiedades de la clase base, hemos creado un constructor por defecto (vacío, es decir, que no sirve para nada), solo porque hemos escogido una opción de las ayudas de del IDE.
Ahora hemos llegado a un punto en el que los objetosCalificacion pueden crearse de dos maneras: la primera, siguiendo el constructor parametrizado enCalificacion. Pero para los objetos de la clase derivada deCalificacion,CalificacionTeoriaPractica, la construcción no implica el constructor anterior, sino el constructor parametrizado deCalificacionTeoriaPractica (donde se inicializan las propiedades directamente), y el constructor por defecto (donde, en realidad, no se hace nada).
Sin querer, hemos violado el principio DRY (No te repitas, oDon't repeat yourself). En el momento en el que la claseCalificacion cambie su manera de construirse, tendremos que tener en cuenta un constructor para los objetos propios, y el constructor por defecto para los objetos de las clases derivadas.
Siguiendo la intuición de que tiene que existir un mundo mejor, ahí fuera, en alguna parte, deshagamos lo hecho y probemos de nuevo, tratando de olvidarnos de los subrayados.
Devolvamos la claseCalificacion a su estado anterior.
publicclassCalificacion:IComparable<Calificacion>{publicCalificacion(Asignaturaasigantura,decimalnota){this.Asignatura=asigantura;this.Nota=nota;}// más cosas...publicdecimalNota{get;}publicAsignaturaAsignatura{get;}}
Y si volvemos al punto de partida, la claseCalificacionTeoriaPractica:
classCalificacionTeoriaPracticas:Calificacion{publicCalificacionTeoriaPracticas(Asignaturaasignatura,decimalteoria,decimalpractica){}}
Podemos, simplemente, llamar al método de la clase base utilizando el inicializadorbase, de la forma más sencilla, sin necesidad de modificar la clase base en absoluto.
classCalificacionTeoriaPracticas:Calificacion{publicCalificacionTeoriaPracticas(Asignaturaasignatura,decimalteoria,decimalpractica):base(asignatura,(teoria+practica)/2){}}
...y ya está. Era tan sencillo como esto.
Ahora imaginémonos que esto ocurre en un proyecto real, en lugar de un escenario imaginario buscando la máxima simplicidad...
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse