En programación informática , el tipado de pato es una aplicación de la prueba del pato —"Si camina como un pato y grazna como un pato, entonces debe ser un pato"— para determinar si un objeto puede usarse para un propósito particular. Con el tipado nominativo , un objeto es de un tipo dado si se declara como tal (o si la asociación de un tipo con el objeto se infiere a través de mecanismos como la herencia de objetos ). Con el tipado de pato, un objeto es de un tipo dado si tiene todos los métodos y propiedades requeridos por ese tipo. [1] [2] El tipado de pato puede verse como una equivalencia estructural basada en el uso entre un objeto dado y los requisitos de un tipo.
Este sencillo ejemplo en Python 3 demuestra cómo cualquier objeto puede usarse en cualquier contexto hasta que se utilice de una manera que no admite.
Clase Pato : def nadar ( yo mismo ): imprimir ( "Pato nadando" ) def volar ( yo mismo ): imprimir ( "Pato volando" )clase Ballena : def nadar ( yo mismo ): imprimir ( "Ballena nadando" )para animal en [ Pato (), Ballena ()]: animal . nadar () animal . volar ()
Producción:
Pato nadando Pato volando Ballena nadando AttributeError: el objeto 'Ballena' no tiene el atributo 'volar'
Si se puede asumir que todo lo que puede nadar es un pato porque los patos pueden nadar, una ballena podría considerarse un pato; sin embargo, si también se asume que un pato debe ser capaz de volar, la ballena no se considerará un pato.
En algunos lenguajes tipados estáticamente como Boo [3] y D , [4] [5] se puede especificar que la verificación de tipo de clase se realice en tiempo de ejecución en lugar de en tiempo de compilación.
El tipado pato es similar al tipado estructural , pero distinto . El tipado estructural es un sistema de tipado estático que determina la compatibilidad y equivalencia de tipos mediante la estructura de un tipo, mientras que el tipado pato es dinámico y determina la compatibilidad de tipos únicamente mediante la parte de la estructura de un tipo a la que se accede durante el tiempo de ejecución .
Los lenguajes TypeScript , [6] Elm [7] y Python [8] admiten la tipificación estructural en distintos grados.
Los protocolos e interfaces proporcionan una forma de declarar explícitamente que algunos métodos, operadores o comportamientos deben definirse. Si una biblioteca de terceros implementa una clase que no se puede modificar, un cliente no puede usar una instancia de ella con una interfaz desconocida para esa biblioteca, incluso si la clase satisface los requisitos de la interfaz. Una solución común a este problema es el patrón adaptador . Por el contrario, con el tipado de pato, el objeto se aceptaría directamente sin la necesidad de un adaptador.
Las funciones o métodos de plantilla (también llamados genéricos ) aplican la prueba duck en un contexto de tipado estático ; esto aporta todas las ventajas y desventajas de la comprobación de tipos estática frente a la dinámica . La tipificación duck también puede ser más flexible, ya que solo se deben implementar los métodos realmente llamados en tiempo de ejecución, mientras que las plantillas requieren implementaciones de todos los métodos que no se puede demostrar que son inalcanzables en tiempo de compilación.
En lenguajes como Java, Scala y Objective-C, se puede emplear la reflexión para inspeccionar si los objetos implementan métodos o agregan los métodos necesarios en tiempo de ejecución. Por ejemplo, la API MethodHandle de Java se puede utilizar de esta manera. [9]