¿Qué es el polimorfismo? Y por qué vale la pena aprender

Si puede conducir un automóvil de cercanías de 4 puertas, también puede conducir una camioneta. Si ha conducido un automóvil con motor de combustión, también puede conducir un automóvil eléctrico.

La forma y el tamaño de los vehículos de pasajeros pueden ser diferentes de uno a otro. El motor que hace funcionar esos vehículos también podría ser completamente diferente. Pero al conductor no le importa.

Simplemente sube, abrocha el cinturón, enciende el vehículo, lo pone en marcha y conduce. Eso es porque los autos, camiones y camionetas son polimórficos .

Polimorfismo: descomponiéndolo

Veamos la palabra polimorfismo. Puede dividirlo en poli , morfología e ismo .

Poly significa muchos, como polígono significa muchos ángulos. Cuando se usa como sustantivo, un morph es una variante de una especie. Y el ismo puede significar sistema.

Entonces, polimorfismo simplemente significa un sistema de muchas variaciones. Sin embargo, eso todavía no le dice mucho sobre cómo se usa en programación. Eso es lo siguiente.

Si camina como un pato … ¿Por qué los objetos polimórficos son impresionantes?

Cuando crea una clase en su código que hereda de otra clase, está vinculando la nueva clase a un contrato. El contrato establece que cada variable y función en el padre también estará en el hijo.

Todos los vehículos tienen volante, pedales de acelerador y freno y una señal de giro. No es necesario abrir el capó para conducir un automóvil. Todo lo que importa es que es un auto.

Lo mismo se aplica a las clases que heredan de otras clases. Aquí hay un ejemplo en TypeScript:

 
class Vehicle {
private _engine: string;
private _tires: number;
constructor(engine: string = "combustion", tires: number = 4) {
this._engine = engine;
this._tires = tires;
}
accelerate(velocity: number) {
console.log("accelerating at a velocity of " + velocity);
}
brake(pressure: number) {
console.log("applying " + pressure + " pressure");
}
turnLeft() {
console.log("turning left");
}
turnRight() {
console.log("turning right");
}
}
class Car extends Vehicle {
}
class Tesla extends Car {
constructor() {
super("electric");
}
}

En este ejemplo, hay una clase de vehículo . La clase Coche hereda de la clase Vehículo . Y Tesla hereda de Car . Ahora creemos un par de objetos y veámoslos.

 let myCoupe: Car = new Vehicle();
console.log(myCoupe);
console.log(myCoupe.constructor.name);
let mySedan: Vehicle = new Tesla();
console.log(mySedan);
console.log(mySedan.constructor.name);
myCoupe.turnLeft();
mySedan.turnLeft();

Puede ver que declaramos myCoupe como un automóvil y mySedan como un vehículo . Luego, creamos myCoupe como un nuevo vehículo y mySedan como un nuevo Tesla . Si visita la zona de pruebas de TypeScript y ejecuta el código, verá que funciona sin errores . Y se comporta como cabría esperar, según el contrato.

En otras palabras, todos los vehículos pueden girar a la izquierda porque lo heredaron de la clase Vehículo . El compilador sabe que todos los hijos de Vehicle aceptaron el contrato. Así que asume que todo está bien, sin importar en qué clases se escribieron o instanciaron los objetos.

A esto a veces se le llama "tipeo de pato". El compilador asume que si camina como un pato y habla como un pato, bien podría ser un pato. Entonces, el compilador no se preocupa por los detalles y simplemente trata el objeto como un pato.

El polimorfismo hace que su código sea a prueba de balas

Otra ventaja del contrato de polimorfismo es la garantía de que su código funcionará. Si ha escrito fuertemente todas sus variables y lo que devuelve cada función, sabrá que cada niño siempre coincidirá con variables, funciones y tipos.

Eso significa que puede agregar y cambiar el código en sus clases sin romper su programa. Cada objeto que hace referencia a un objeto Vehículo siempre obtendrá datos y funciones que cumplan con las expectativas, sin importar cuánto cambie el Coche .

Es posible que el código dentro de la función no muestre los resultados correctos. Pero ese es un problema diferente. Siempre que la función siga el contrato y devuelva el tipo esperado de variable, no resultará en un error de descifrado de código.

El polimorfismo es enorme, y aquí hay 10 principios de programación más que debe conocer .

Practica el polimorfismo

  • Utilice el enlace de la caja de arena de arriba para crear una clase Barco .
  • Cree una instancia de un nuevo objeto de barco de tal manera que sea un tipo de vehículo , pero aún se vea como un barco.
  • Asegúrese de que el barco todavía se comporte como un vehículo.

Un último ejemplo de polimorfismo

El polimorfismo puede ser un concepto complicado de comprender inicialmente. Pero una vez que lo obtiene, ha dado un gran paso hacia la comprensión de qué es realmente la programación orientada a objetos. Sin embargo, el concepto aún puede parecer teórico. Así que aquí hay un ejemplo sólido del mundo real para ayudarlo a ver cuán útil es.

Imagina que estás creando una aplicación web que se conecta a una base de datos MySQL. Luego, el jefe decide cambiar a una base de datos PostgreSQL. ¿Eso significa que tiene que volver a escribir todas las llamadas a su base de datos?

No, no es así. Si su aplicación usa una clase DataAccess con subclases que realmente se entretienen con los datos, está de suerte. La clase DataAccess define cómo interactúa su aplicación con los datos, no cómo interactúa con la base de datos.

Tiene subclases como MySQLAccess y PostgresQLAccess que hacen todo el trabajo sucio. Pero si su aplicación solo tiene objetos DataAccess , puede intercambiar bases de datos sin volver a escribir una sola línea de código de la aplicación.