Polimorfismo en Programación Orientada a Objetos

Clase 4 de 35Curso de C# con .Net Core 2.1

Resumen

El polimorfismo en C# cobra sentido cuando ves un mismo objeto desde distintas referencias. Aquí se demuestra con claridad cómo un Alumno, que hereda de ObjetoEscuela, puede tratarse uniformemente como su padre, cómo imprimir sus datos y qué ocurre al convertir referencias entre padre e hijo. Sin teorías extra: solo código, resultados y buenas prácticas.

¿Qué es polimorfismo y cómo verlo en código?

El punto de partida es simple y potente: una instancia de Alumno se puede ver como ObjetoEscuela porque hereda de esa clase. Así, accedemos a atributos comunes como nombre e ID único, y comprobamos que es el mismo objeto al coincidir los valores.

// Crear Alumno y asignarlo a variable de tipo base
var alumnoTest = new Alumno { Nombre = "Claire Underwood" };
ObjetoEscuelaBase ob = alumnoTest; // Polimorfismo: hijo visto como padre.

// Imprimir datos compartidos
Console.WriteLine($"Alumno: {alumnoTest.Nombre}, ID: {alumnoTest.UniqueId}.");
Console.WriteLine($"Objeto escuela: {ob.Nombre}, ID: {ob.UniqueId}.");

¿Por qué el tipo sigue siendo alumno?

Aunque uses una referencia de tipo padre, el tipo real del objeto no cambia: es Alumno. Por eso, al consultar el tipo, en ambos casos aparece Alumno. Esto valida que polimorfismo significa múltiples formas de ver la misma instancia, no duplicarla.

  • Un Alumno hereda de ObjetoEscuela.
  • La referencia base accede solo a miembros comunes.
  • El ID único igual en ambas impresiones confirma que es la misma instancia.

¿Cómo afectan las conversiones y el casting al trabajar con herencia?

La compatibilidad es unidireccional: puedes ver al hijo como padre, pero no al padre como hijo, salvo que el objeto padre realmente contenga un hijo.

¿Cuándo es válido convertir de padre a hijo?

Cuando la referencia base apunta a un Alumno, la conversión explícita es válida y segura.

// Referencia base que realmente contiene un Alumno
ObjetoEscuelaBase ob = alumnoTest;
var alumnoOtraVez = (Alumno)ob; // Cast válido porque ob es un Alumno.

Console.WriteLine($"Alumno otra vez: {alumnoOtraVez.Nombre}, ID: {alumnoOtraVez.UniqueId}.");

¿Cuándo falla y lanza excepción?

Si instancias un ObjetoEscuelaBase “puro” (para la demostración se quitó temporalmente la palabra abstract), forzar un cast a Alumno lanza excepción: ese objeto padre no tiene las características del hijo.

// Objeto de la clase base (tras quitar *abstract* para la prueba)
var dummy = new ObjetoEscuelaBase { Nombre = "Frank Underwood" };

// Cast inválido: este objeto nunca fue un Alumno
var alumnoInvalido = (Alumno)dummy; // Lanza excepción en tiempo de ejecución.
  • La conversión de padre a hijo solo procede si el contenido es realmente del tipo hijo.
  • Un cast forzado sobre un objeto base que no es un Alumno provoca error.
  • La referencia no cambia el objeto: solo cómo lo ves y qué miembros puedes usar.

¿Qué prácticas y herramientas se aplican durante el ejercicio?

Además del concepto, se usaron herramientas y técnicas que potencian el flujo de trabajo y la legibilidad.

  • Renombrar método con refactoring en Visual Studio: clic derecho, renombrar symbol.
  • Mantener consistencia de nombres: cambiar a DrawLine en la clase printer.
  • Impresión con interpolación de cadenas: $"texto {variable}" para mostrar nombre e ID.
  • Ejecución constante para validar resultados: dotnet run y observar la salida.
  • Conceptos practicados: herencia, polimorfismo, compatibilidad de tipos, clase base, clase hija, ID único, conversión explícita (casting), excepción por cast inválido, clase abstract y tipo en tiempo de ejecución.

¿Te gustaría que mostremos cómo detectar de forma segura el tipo antes de castear o integrar estas pruebas con tu printer? Comparte tus dudas y casos prácticos en los comentarios.