Esta característica permite que, sin alterar ni tocar el código existente, se puedan incorporar nuevos comportamientos y funciones (es decir la interfaz sintáctica se mantiene inalterada pero cambia el comportamiento en función de qué objeto estamos usando en cada momento).
El único requisito es que los objetos deben ser capaces de responder al mensaje que se les envía, garantizando así una flexibilidad y extensibilidad en el diseño del software.
Así, distintos objetos podrán intercambiarse en tiempo de ejecución –siempre que sean del mismo tipo–, y además con dependencias mínimas entre ellos.
Lo anterior se hace aún más evidente en lenguajes de programación orientada a objetos basados en prototipos, como Self, en los que las clases no existen.
Además, es importante remarcar que si un cierto grupo de objetos pueden utilizarse de manera polimórfica es porque, en última instancia, todos ellos saben responder a un cierto mensaje (o a varios), pero dado que esos mismos objetos generalmente contendrán otros métodos (que otros objetos en dicho grupo no contienen), difícilmente se pueda decir lisa y llanamente que los objetos son polimórficos; lo correcto es decir que esos objetos se pueden utilizar de modo polimórfico para un cierto conjunto de mensajes.
Podemos crear dos clases distintas: Pez y Ave que heredan de la superclase Animal.
Debe notarse que la instancia de la interfaz accede a sus métodos aunque en sus clases se hayan declarado privadas.
El polimorfismo como se muestra en el ejemplo anterior, suele ser bastante ventajoso aplicado desde las interfaces, ya que permite crear nuevos tipos sin necesidad de tocar las clases ya existentes (imaginemos que deseamos añadir una clase Multiplicar), basta con recompilar todo el código que incluye los nuevos tipos añadidos.
Si se hubiera recurrido a la sobrecarga durante el diseño exigiría retocar la clase anteriormente creada al añadir la nueva operación Multiplicar, lo que además podría suponer revisar todo el código donde se instancia a la clase.