El Polimorfismo es la Clave

En este artículo analizamos, a través de un ejemplo, el Polimorfismo como característica clave de los lenguajes orientados a objetos.

 

En este artículo analizamos, a través de un ejemplo, el Polimorfismo como característica clave de los lenguajes orientados a objetos.

Índice de contenido

1. Introducción

Clean Code, Principios de diseño (SOLID, DRY, IoC…), inyección de dependencias, patrones de diseño… son todos conceptos, técnicas, principios, que nos aportan conocimientos indispensables para desarrollar software de calidad, pero hay una característica de los lenguajes orientados a objetos que es clave para implementar y comprender la mayoría de estos conceptos más avanzados: El polimorfismo.

La palabra Polimorfismo significa «múltiples formas». En el caso de la programación orientada a objetos (POO) el polimorfismo está más ligado al comportamiento, por lo que pudiéramos ver más su significado como «múltiples comportamientos». Más formalmente podemos definir el polimorfismo como la característica que le permite a un cliente enviar un mensaje a objetos de diferentes tipos sin conocer exactamente el tipo que se está usando. El único requisito que deben de cumplir estos objetos es saber responder a dicho mensaje. De esta manera, bajo un mismo símbolo (el método o mensaje usado) se van a ejecutar comportamientos diferentes dependiendo de a qué objeto apunte la variable de referencia que usamos para enviar el mensaje.

Aunque en este artículo nos vamos a centrar en el polimorfismo de tipo inclusión o controlado por la herencia (subtype polymorphism), existen otros tipos de polimorfismos que es conveniente conocer.

2. Tipos de polimorfismo

Luca Cardelli en el artículo On Understanding Types, Data Abstraction, and Polymorphism agrupa los tipos de polimorfismo en las siguientes categorías:

Universal (True polymorphism)

  • Parametric: Se refiere a la parametrización de tipos (Genericidad).
  • Inclusion o subtyping: Es al que nos referimos casi siempre cuando hablamos de polimorfismo en los lenguajes de POO. Está basado en la herencia/implementación de clases/interfaces.

 

Ad-hoc (Apparent polymorphism)

  • Overloading: Sobrecarga de métodos.
  • Coersion: Casting implicito y explicito.

 

Solo la primera categoría agrupa los tipos que se conocen como polimorfismo verdadero porque es en tiempo de ejecución cuando se determina que comportamiento ejecutar (Late binding). El resto se resuelve en tiempo de compilación, por lo que podemos decir que es un polimorfismo aparente.

Por ejemplo, en la sobrecarga de métodos (Overloading) puede parecer que el método sobrecargado se comporta de varias formas, pero en realidad se invoca a distintos métodos dependiendo del número, orden y tipo de los parámetros. Es decir, el compilador reemplaza la llamada al método a partir de la signatura de éste (Static binding).

3. Un ejemplo

Veamos el uso del polimorfismo a través de un ejemplo sencillo. Los requisitos son los siguientes: dado un texto plano y el nombre de un algoritmo de encriptación, el programa tiene que imprimir por pantalla el texto encriptado utilizando dicho algoritmo. Para implementarlo vamos a utilizar el patrón de diseño Strategy combinado con una factoría que nos dará el algoritmo de encriptación a utilizar a partir del nombre de éste.

import java.util.HashMap;
import java.util.Map;

public class PolymorphismDemo {

    public static final void main(String[] args) {
        String plainText = args[0];
        Algorithm algorithm = Algorithm.valueOf(args[1]);

        EncryptionStrategy encryptionStrategy = EncryptionStrategyFactory.getInstance(algorithm);

        String encryptedText = encryptionStrategy.encrypt(plainText);

        System.out.println(
            String.format("Text encrypted using '%s' algorithm: %s", 
                algorithm, encryptedText)
        );
    }

    enum Algorithm {
        AES, TWOFISH
    }

    interface EncryptionStrategy {
        String encrypt(String input);
    }

    static class EncryptionStrategyFactory {

        public static Map<Algorithm, EncryptionStrategy> encryptionStrategies = new 
            HashMap<Algorithm, EncryptionStrategy>();

        static {
            registerStrategy(Algorithm.AES, (input) -> "aes:" + input);
            registerStrategy(Algorithm.TWOFISH, (input) -> "twofish:" + input);
        }

        public static EncryptionStrategy getInstance(Algorithm name) {
            return encryptionStrategies.get(name);
        }

        public static void registerStrategy(Algorithm algorithm, EncryptionStrategy encryptionStrategy) {
            encryptionStrategies.put(algorithm, encryptionStrategy);
        }

    }

}

 

En la línea 12 es donde ocurre la magia. El cliente, a través del mensaje ‘encrypt’, va a ejecutar comportamientos diferentes dependiendo de a qué estrategia concreta apunta la variable encryptionStrategy, sin conocer realmente el tipo de algoritmo que se está utilizando.

Indiscutiblemente estamos aplicando otros conceptos de la POO. Nos estamos abstrayendo porque el código cliente que usa el algoritmo de encriptación está expresando en términos generales, además representamos el comportamiento común en la abstracción EncryptionStrategy. Encapsulando porque los detalles de cada implementación se ocultan. Aunque no usemos la herencia, las estrategias concretas implementan la interfaz EncryptionStrategy creando una relación Is-A entre diferentes objetos. Pero realmente, es la posibilidad de ejecutar comportamientos diferentes bajo un mismo mensaje lo que le da flexibilidad al código.

Si hacemos una análisis de los conceptos que hemos aplicado. Tenemos el principio de Abierto/Cerrado, añadir nuevos algoritmos no implica modificar el código cliente, solo tendríamos que registrarlo en la factoría. Tenemos el patrón de diseño Strategy, que nos da solución a la problemática de cambiar algoritmos en tiempo de ejecución. Y en la base, como característica del lenguaje, tenemos el polimorfismo, que nos permite ejecutar distintos algoritmos de encriptación utilizando una misma llamada (encrypt(input)) sin conocer exactamente el algoritmo específico que se está utilizando.

3. Conclusiones

Es importante entender el concepto de polimorfismo como base para entender otros conceptos más avanzados. Principios de diseño como Abierto/Cerrado e IoC, técnicas como la inyección de dependencias y muchas de las implementaciones de patrones de diseños tienen como base esta característica clave del lenguaje.

3. Referencias

Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

He leído y acepto la política de privacidad

Información básica acerca de la protección de datos

  • Responsable: IZERTIS S.A.
  • Finalidad: Envío información de carácter administrativa, técnica, organizativa y/o comercial sobre los productos y servicios sobre los que se nos consulta.
  • Legitimación: Consentimiento del interesado
  • Destinatarios: Otras empresas del Grupo IZERTIS. Encargados del tratamiento.
  • Derechos: Acceso, rectificación, supresión, cancelación, limitación y portabilidad de los datos.
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad

Consultor tecnológico de desarrollo de proyectos informáticos.
Ingeniero en Informática.
Experto Java/Java EE. OCA Java SE 8 Programmer
Puedes encontrarme en Autentia: ofrecemos servicios de soporte a desarrollo, factoría y formación. Somos expertos en Java/Java EE

¿Quieres publicar en Adictos al trabajo?

Te puede interesar

02/03/2026

José Antonio Sánchez Segovia

Zephyr es un RTOS open source respaldado por la Linux Foundation que permite desarrollar dispositivos embebidos conectados, eficientes y escalables, facilitando el paso de prototipo a producto final con una arquitectura mantenible.

23/02/2026

Enrique Casado Díez

LoRa y LoRaWAN son tecnologías clave en el ecosistema IoT cuando se requiere largo alcance y bajo consumo energético. En este artículo analizamos su funcionamiento, Spreading Factor, link budget, arquitectura de red, frecuencias y clases de dispositivos, con un caso práctico real.

19/02/2026

Juan José Díaz Antuña

Copilot Chat es la forma más sencilla y segura de empezar a usar IA en Microsoft 365. En este artículo vemos cómo funciona, cómo activarlo y en qué se diferencia de Microsoft 365 Copilot, Copilot Studio y los Agentes Inteligentes, con ejemplos prácticos y una comparativa clara.