Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprende Polimorfismo | Principios de POO
C# Más Allá de lo Básico

bookPolimorfismo

El término Polimorfismo significa "ocurrir en varias formas diferentes". En el contexto de la programación orientada a objetos, el polimorfismo se refiere a la capacidad de una clase para proporcionar una interfaz común para sus clases derivadas, permitiendo al mismo tiempo que cada clase derivada implemente comportamientos específicos para los métodos heredados.

Normalmente, al crear un objeto de una clase, se crea una variable para almacenar la referencia de ese objeto. Y el tipo de la variable suele ser la clase de ese objeto.

Por ejemplo:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

Sin embargo, también se puede crear una variable de una clase base y almacenar en ella un objeto de una clase derivada.

Por ejemplo:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

El atributo breed del objeto Dog no es accesible porque, cuando almacenas el objeto Dog en una variable de tipo Mammal, este se convierte implícitamente en Mammal. Esto significa que solo puedes acceder a los atributos y métodos presentes en la clase Mammal. No significa que el valor almacenado en la clase breed se pierda, simplemente es inaccesible y, en esencia, está oculto.

Puedes convertir fácilmente example en un Dog mediante una conversión de tipo explícita, y el atributo breed volverá a estar disponible:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

Sin embargo, para los métodos existe una característica adicional llamada sobrescritura de métodos (method overriding), que es algo similar a la sobrecarga de métodos (method overloading). En este caso, básicamente se redefine un método de una clase base en la clase derivada.

Por ejemplo, es posible que desee que Mammal tenga un método speak() de modo que muestre Woof! si se llama desde un objeto Dog, y Meow! si se llama desde un objeto Cat:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Las advertencias que aparecen durante la compilación se deben a la coincidencia de nombres de métodos en las clases padre e hija. En este caso, hay coincidencia entre los métodos speak de las clases Cat y Mammal, y también entre Dog y Mammal, por lo que se generan dos advertencias.

Sin embargo, observe que al final m1, m2 y m3 ejecutan el método definido en la clase Mammal, ya que han sido convertidos a objetos de tipo Mammal.

Si desea que el método speak se comporte como lo hace en su objeto original, simplemente puede convertirlo en un método virtual (virtual method). Un método virtual es simplemente un método que permite ser sobrescrito desde clases derivadas de tal manera que la implementación específica que se ejecuta se determina en tiempo de ejecución según el tipo del objeto original.

Para hacer que un método sea virtual, simplemente agregue la palabra clave virtual antes de su tipo de retorno:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

Para crear una implementación sobrescrita de este método, utiliza la palabra clave override antes del tipo de retorno en la implementación de la clase derivada de esa nueva versión:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

Ahora combinemos los dos fragmentos y observemos cómo afecta la salida:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Se observa que en la salida, m2 y m3 utilizan la implementación del método de Cat y Dog porque esos objetos originalmente eran Cat y Dog. Todo este proceso de sobrescribir métodos para que se comporten según su tipo original se denomina polimorfismo.

Una situación en la que esto puede ser muy útil es la posibilidad de almacenar objetos de diferentes tipos de datos en un solo arreglo o lista.

Por ejemplo:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. ¿Cuáles son las dos palabras clave utilizadas en la sobrescritura de métodos?

2. ¿Cuál es la forma correcta de hacer que un método sea sobrescribible?

question mark

¿Cuáles son las dos palabras clave utilizadas en la sobrescritura de métodos?

Select the correct answer

question mark

¿Cuál es la forma correcta de hacer que un método sea sobrescribible?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 5. Capítulo 4

Pregunte a AI

expand

Pregunte a AI

ChatGPT

Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla

Awesome!

Completion rate improved to 2.04

bookPolimorfismo

Desliza para mostrar el menú

El término Polimorfismo significa "ocurrir en varias formas diferentes". En el contexto de la programación orientada a objetos, el polimorfismo se refiere a la capacidad de una clase para proporcionar una interfaz común para sus clases derivadas, permitiendo al mismo tiempo que cada clase derivada implemente comportamientos específicos para los métodos heredados.

Normalmente, al crear un objeto de una clase, se crea una variable para almacenar la referencia de ese objeto. Y el tipo de la variable suele ser la clase de ese objeto.

Por ejemplo:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

Sin embargo, también se puede crear una variable de una clase base y almacenar en ella un objeto de una clase derivada.

Por ejemplo:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

El atributo breed del objeto Dog no es accesible porque, cuando almacenas el objeto Dog en una variable de tipo Mammal, este se convierte implícitamente en Mammal. Esto significa que solo puedes acceder a los atributos y métodos presentes en la clase Mammal. No significa que el valor almacenado en la clase breed se pierda, simplemente es inaccesible y, en esencia, está oculto.

Puedes convertir fácilmente example en un Dog mediante una conversión de tipo explícita, y el atributo breed volverá a estar disponible:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

Sin embargo, para los métodos existe una característica adicional llamada sobrescritura de métodos (method overriding), que es algo similar a la sobrecarga de métodos (method overloading). En este caso, básicamente se redefine un método de una clase base en la clase derivada.

Por ejemplo, es posible que desee que Mammal tenga un método speak() de modo que muestre Woof! si se llama desde un objeto Dog, y Meow! si se llama desde un objeto Cat:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Las advertencias que aparecen durante la compilación se deben a la coincidencia de nombres de métodos en las clases padre e hija. En este caso, hay coincidencia entre los métodos speak de las clases Cat y Mammal, y también entre Dog y Mammal, por lo que se generan dos advertencias.

Sin embargo, observe que al final m1, m2 y m3 ejecutan el método definido en la clase Mammal, ya que han sido convertidos a objetos de tipo Mammal.

Si desea que el método speak se comporte como lo hace en su objeto original, simplemente puede convertirlo en un método virtual (virtual method). Un método virtual es simplemente un método que permite ser sobrescrito desde clases derivadas de tal manera que la implementación específica que se ejecuta se determina en tiempo de ejecución según el tipo del objeto original.

Para hacer que un método sea virtual, simplemente agregue la palabra clave virtual antes de su tipo de retorno:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

Para crear una implementación sobrescrita de este método, utiliza la palabra clave override antes del tipo de retorno en la implementación de la clase derivada de esa nueva versión:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

Ahora combinemos los dos fragmentos y observemos cómo afecta la salida:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Se observa que en la salida, m2 y m3 utilizan la implementación del método de Cat y Dog porque esos objetos originalmente eran Cat y Dog. Todo este proceso de sobrescribir métodos para que se comporten según su tipo original se denomina polimorfismo.

Una situación en la que esto puede ser muy útil es la posibilidad de almacenar objetos de diferentes tipos de datos en un solo arreglo o lista.

Por ejemplo:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. ¿Cuáles son las dos palabras clave utilizadas en la sobrescritura de métodos?

2. ¿Cuál es la forma correcta de hacer que un método sea sobrescribible?

question mark

¿Cuáles son las dos palabras clave utilizadas en la sobrescritura de métodos?

Select the correct answer

question mark

¿Cuál es la forma correcta de hacer que un método sea sobrescribible?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 5. Capítulo 4
some-alt