Duck typing

From Wikipedia, the free encyclopedia

En los lenguajes de programación orientados a objetos, se conoce como duck typing o tipado pato el estilo de tipificación dinámica de datos en que el conjunto actual de métodos y propiedades determina la validez semántica, en vez de que lo hagan la herencia de una clase en particular o la implementación de una interfaz específica. El nombre del concepto se refiere a la prueba del pato, una humorada de razonamiento inductivo atribuida a James Whitcomb Riley (ver Historia más abajo), que pudo ser como sigue:

"Cuando veo un ave que camina como un pato, nada como un pato y suena como un pato, a esa ave yo la llamo un pato."[1][2]

En duck typing, el programador solo se ocupa de los aspectos del objeto que van a usarse, y no del tipo de objeto que se trata. Por ejemplo en un lenguaje sin duck-typing uno puede crear una función que toma un objeto de tipo Pato y llama los métodos "caminar" y "parpar" de ese objeto. En un lenguaje con duck-typing, la función equivalente tomaría un objeto de cualquier tipo e invocaría los métodos caminar y parpar. Si el objeto tratado no tiene los métodos pedidos, la función enviará una señal de error en tiempo de ejecución. Este hecho de que la función acepte cualquier tipo de objeto que implemente correctamente los métodos solicitados es lo que evoca la cita precedente y da nombre a la forma de tipificación.

El Duck typing usualmente es acompañado por el hábito de no probar el tipo de los argumentos en los métodos y funciones, y en vez de eso confiar en la buena documentación, el código claro y la prueba para asegurar el uso correcto. Los usuarios de lenguajes con tipificado estático al iniciarse con lenguajes de tipificado dinámico a menudo se ven tentados a agregar chequeos de tipo estáticos (previos a ejecución), desaprovechando la flexibilidad y beneficios del duck typing y restringiendo el dinamismo del lenguaje.

Considera el siguiente pseudocódigo para un lenguaje con duck-typing:

función calcular(a, b, c) => devuelve (a+b)*c

ejemplo1 = calcular (1, 2, 3)
ejemplo2 = calcular ([1, 2, 3], [4, 5, 6], 2)
ejemplo3 = calcular ('manzanas ', 'y naranjas, ', 3)

mostrar a_cadena ejemplo1
mostrar a_cadena ejemplo2
mostrar a_cadena ejemplo3

En el ejemplo, cada vez que se llama la función calcular se pueden emplear objetos sin relación de herencia (números, listas y cadenas). En tanto y en cuanto los objetos soporten los métodos "+" y "*" la operación tendrá éxito. Si se traduce este algoritmo a Ruby o Python por ejemplo, el resultado de la ejecución será:

9
[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
manzanas y naranjas, manzanas y naranjas, manzanas y naranjas,  

Así, el duck typing permite polimorfismo sin herencia. El único requerimiento de la función calcular para las variables es que soporten los métodos "+" y "*".

La prueba del pato puede verse en el siguiente ejemplo (en Python). Hasta donde a la función en_el_bosque le importa, el objeto es un pato:

class Pato:
    def parpar(self): 
        print "Cuac!"
    def plumas(self): 
        print "El pato tiene plumas blancas y grises."
 
class Persona:
    def parpar(self):
        print "La persona imita el sonido de un pato."
    def plumas(self): 
        print "La persona toma una pluma del suelo y la muestra."
 
def en_el_bosque(pato):
    pato.parpar()
    pato.plumas()
 
def juego():
    donald = Pato()
    juan = Persona()
    en_el_bosque(donald)
    en_el_bosque(juan)

juego()

Duck typing en lenguajes de tipificación estática

Ciertos lenguajes que usualmente son de tipificación estática como Boo y la versión 4 de C# tienen anotaciones extra de tipos[3][4] que instruyen al compilador para que disponga el chequeo de tipo de las clases en tiempo de ejecución y no en tiempo de compilación, y que incluya código de chequeo de tipos en tiempo de ejecución en la salida compilada. Estos agregados permiten al lenguaje gozar de la mayor parte de los beneficios del duck-typing con la única desventaja de tener que identificar y especificar qué clases serán dinámicas en tiempo de compilación.

Comparación con otros tipos de tipificación

Sistemas de tipificación estructural

El duck typing es similar pero diferente a la tipificación estructural. La tipificación estructural es un sistema de tipificación estática que determina la compatibilidad y la equivalencia de tipos según su estructura, mientras que el duck typing es dinámico y determina dicha compatibilidad basándose en la parte de la estructura que se accede en tiempo de ejecución.
El lenguaje de programación Objective Caml usa un sistema de tipificación estructural.

Interfaces

Las interfaces pueden proveer algunos de los beneficios del duck typing pero este es diferente en cuanto no se define explícitamente una interfaz. Por ejemplo, si una librería Java de terceros implementa una clase que no es posible modificar, no se podrá usar una instancia de esa clase en lugar de una interfaz definida por uno mismo, mientras que el duck typing sí permite hacerlo.

Templates o tipos genéricos

Los Template, funciones o métodos genéricos aplican la prueba del pato en un contexto de tipificación estática; esto reúne todas las ventajas y desventajas de la tipificación estática contra la tipificación dinámica en general. El duck typing puede también ser más flexible en que solo los métodos llamados en tiempo de ejecución necesitan ser implementados, mientras que los templates requieren que se implemente todos los métodos que no deban resultar inaccesibles en tiempo de compilación.

Puede mencionarse como ejemplos los lenguajes C++ y D con templates, que derivaron de los genéricos de Ada.

Críticas

Una crítica citada a menudo dice:

Un problema con el duck typing es que fuerza al programador a tener un entendimiento mucho más amplio del código con que está trabajando en todo momento. En un lenguaje con tipificación estática y fuerte que use controles de tipo en jerarquías y parámetros, es mucho más difícil pasarle un tipo inesperado de objeto a una clase. Por ejemplo en Python podrías fácilmente crear una clase llamada Vino, que espera una clase que implemente el atributo "prensa" como un ingrediente. Sin embargo una clase llamada Imprenta podría también implementar un método llamado prensa(). Con duck typing, para poder prevenir errores extraños y difíciles de detectar el desarrollador debe ser consciente de cada uso potencial del método "prensa", aunque esté conceptualmente desvinculado del tema con que esté trabajando.
Esencialmente, el problema es que "si camina como pato y se oye como pato", podría ser un dragón haciendo el pato. No siempre querrás dejar los dragones en el estanque, aunque sepan hacerse pasar por patos.

Los defensores del duck typing como Guido van Rossum argumentan que el asunto se maneja con pruebas, y con el conocimiento del código necesario para mantenerlo.[5][6]

Las críticas acerca del duck typing tienden a ser casos especiales de aspectos más amplios relacionados con la disputa entre la tipificación estática y la dinámica.

Historia

Alex Martelli hizo uso precoz (2000) del término en un mensaje del grupo de noticias comp.lang.python. También resaltó la malinterpretación de la prueba literal del pato, lo que podría indicar que el término ya era usado.

En otras palabras, no chequeen si ES un pato, chequeen si PARPA como pato, CAMINA como pato, etc, etc, dependiendo de exactamente qué parte de la conducta de un pato necesitan para jugar su juego de lenguaje..

Implementaciones

Referencias

Enlaces externos

Related Articles

Wikiwand AI