Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Baltasar García Perez-Schofield
Baltasar García Perez-Schofield

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...

Empezando con la clase **Calificacion**

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.

Y el constructor de **Calificacion**

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:

MecanismoSignificado
Inicializador 'base'Ejecuta el constructor de la clase base con los parámetros dados
Constructor por defectoConstructor 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(){}}
Enter fullscreen modeExit fullscreen mode

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;}}
Enter fullscreen modeExit fullscreen mode

¡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;}}
Enter fullscreen modeExit fullscreen mode

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}");
Enter fullscreen modeExit fullscreen mode

Así que compilo, ejecuto, y... sucede algo raro.

Unhandled exception. System.NotImplementedException: The method or operation is not implemented.
Enter fullscreen modeExit fullscreen mode

¡¿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();}// ...}
Enter fullscreen modeExit fullscreen mode

¿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(){}// ...}
Enter fullscreen modeExit fullscreen mode

Veamos, el problema ha desaparecido. Una compilación y ejecución más tarde...

Matracas: 7,8Matracas: 6,5
Enter fullscreen modeExit fullscreen mode

¡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;}}
Enter fullscreen modeExit fullscreen mode

Y si volvemos al punto de partida, la claseCalificacionTeoriaPractica:

classCalificacionTeoriaPracticas:Calificacion{publicCalificacionTeoriaPracticas(Asignaturaasignatura,decimalteoria,decimalpractica){}}
Enter fullscreen modeExit fullscreen mode

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){}}
Enter fullscreen modeExit fullscreen mode

...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...

Continua...

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Lecturer in programming since 1998
  • Location
    Spain
  • Work
    Associate professor at University of Vigo
  • Joined

More fromBaltasar García Perez-Schofield

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp