De Wikipedia, la enciclopedia libre
  (Redirigido del tipo polimorfismo )
Saltar a navegación Saltar a búsqueda

En los lenguajes de programación y la teoría de tipos , el polimorfismo es la provisión de una única interfaz a entidades de diferentes tipos [1] o el uso de un solo símbolo para representar múltiples tipos diferentes. [2]

Las principales clases de polimorfismo más comúnmente reconocidas son:

  • Polimorfismo ad hoc : define una interfaz común para un conjunto arbitrario de tipos especificados individualmente.
  • Polimorfismo paramétrico : cuando uno o más tipos no se especifican por nombre sino por símbolos abstractos que pueden representar cualquier tipo.
  • Subtipado (también llamado polimorfismo de subtipo o polimorfismo de inclusión ): cuando un nombre denota instancias de muchas clases diferentes relacionadas por alguna superclase común. [3]

Historia [ editar ]

El interés por los sistemas de tipos polimórficos se desarrolló significativamente en la década de 1960, y las implementaciones prácticas comenzaron a aparecer a fines de la década. Polimorfismo Ad hoc y polimorfismo paramétrico fueron descritas originalmente en Christopher Strachey 's conceptos fundamentales de Lenguajes de Programación , [4] en el que se enumeran como 'las dos clases principales' de polimorfismo. El polimorfismo ad hoc fue una característica de Algol 68 , mientras que el polimorfismo paramétrico fue la característica central del sistema de tipos de ML .

En un artículo de 1985, Peter Wegner y Luca Cardelli introdujeron el término polimorfismo de inclusión para modelar subtipos y herencia , [2] citando a Simula como el primer lenguaje de programación en implementarlo.

Tipos [ editar ]

Polimorfismo ad hoc [ editar ]

Christopher Strachey eligió el término polimorfismo ad hoc para referirse a funciones polimórficas que se pueden aplicar a argumentos de diferentes tipos, pero que se comportan de manera diferente según el tipo de argumento al que se aplican (también conocido como sobrecarga de funciones o sobrecarga de operadores ). [5] El término " ad hoc " en este contexto no pretende ser peyorativo; se refiere simplemente al hecho de que este tipo de polimorfismo no es una característica fundamental del sistema de tipos. En el ejemplo de Pascal / Delphi a continuación, elAdd las funciones parecen funcionar genéricamente sobre varios tipos cuando se observan las invocaciones, pero el compilador las considera dos funciones completamente distintas a todos los efectos:

programa  Adhoc ;función  Suma ( x ,  y  :  Integer )  :  Integer ; comenzar  Suma  : =  x  +  y final ;función  Agregar ( s ,  t  :  String )  :  String ; begin  Add  : =  Concat ( s ,  t ) end ;comenzar  Writeln ( Agregar ( 1 ,  2 )) ;  (* Imprime "3" *)  Writeln ( Add ( 'Hola,' ,  'Mamíferos!' )) ;  (* Imprime "¡Hola, Mamíferos!" *) Fin .

En los lenguajes tipados dinámicamente , la situación puede ser más compleja, ya que la función correcta que debe invocarse solo se puede determinar en tiempo de ejecución.

La conversión de tipo implícita también se ha definido como una forma de polimorfismo, denominado "polimorfismo de coerción". [2] [6]

Polimorfismo paramétrico [ editar ]

El polimorfismo paramétrico permite escribir una función o un tipo de datos de forma genérica, de modo que pueda manejar valores de manera uniforme sin depender de su tipo. [7] El polimorfismo paramétrico es una forma de hacer que un lenguaje sea más expresivo sin dejar de mantener una seguridad de tipo estática total .

El concepto de polimorfismo paramétrico se aplica tanto a los tipos de datos como a las funciones . Una función que puede evaluarse o aplicarse a valores de diferentes tipos se conoce como función polimórfica. Un tipo de datos que puede parecer de tipo generalizado (por ejemplo, una lista con elementos de tipo arbitrario) se designa como tipo de datos polimórficos como el tipo generalizado a partir del cual se realizan tales especializaciones.

El polimorfismo paramétrico es omnipresente en la programación funcional, donde a menudo se lo denomina simplemente "polimorfismo". El siguiente ejemplo en Haskell muestra un tipo de datos de lista parametrizada y dos funciones paramétricamente polimórficas en ellos:

 Lista de  datos a  =  Nil  |  Contras  a  ( Lista  a )longitud  ::  Lista  a  ->  Longitud entera Nil = 0 longitud ( Cons x xs ) = 1 + longitud xs           mapa  ::  ( a  ->  b )  ->  Lista  a  ->  Lista  b mapa  f  Nil  =  Nulo mapa  f  ( Contras  x  xs )  =  Contras  ( f  x )  ( mapa  f  xs )

El polimorfismo paramétrico también está disponible en varios lenguajes orientados a objetos. Por ejemplo, plantillas en C ++ y D, o bajo el nombre genéricos en C #, Delphi y Java:

class  List < T >  {  class  Node < T >  {  T  elem ;  Nodo < T >  siguiente ;  }  Cabezal de nodo < T >  ; int length () { ... } }     Lista < B >  mapa ( Func < A ,  B >  f ,  lista < A >  xs )  {  ... }

John C. Reynolds (y más tarde Jean-Yves Girard ) desarrolló formalmente esta noción de polimorfismo como una extensión del cálculo lambda (llamado cálculo lambda polimórfico o Sistema F ). Cualquier función paramétricamente polimórfica está necesariamente restringida en lo que puede hacer, trabajando en la forma de los datos en lugar de su valor, lo que lleva al concepto de parametricidad .

Subtipado [ editar ]

Algunos lenguajes emplean la idea de subtipo (también llamado polimorfismo de subtipo o polimorfismo de inclusión ) para restringir el rango de tipos que se pueden usar en un caso particular de polimorfismo. En estos lenguajes, la subtipificación permite escribir una función para tomar un objeto de cierto tipo T , pero también funcionar correctamente, si se le pasa un objeto que pertenece a un tipo S que es un subtipo de T (según el principio de sustitución de Liskov ) . Esta relación tipo se escribe a veces S  <:  T . Por el contrario, se dice que T es un supertipo de S-Escrito T  :>  S . El polimorfismo de subtipo generalmente se resuelve dinámicamente (ver más abajo).

En el siguiente ejemplo, creamos subtipos de animales de perros y gatos. El procedimiento letsHear()acepta un animal, pero también funcionará correctamente si se le pasa un subtipo:

 clase  abstracta Animal  {  charla de cadena abstracta  (); } class  Cat  extiende  Animal  {  String  talk ()  {  return  "¡Miau!" ;  } }class  Perro  extiende  Animal  {  String  talk ()  {  return  "¡Guau!" ;  } }static  void  letsHear ( animal final  a ) { println ( a . talk ()); }   static  void  main ( String []  args )  {  letsHear ( new  Cat ());  letsHear ( nuevo  perro ()); }

En otro ejemplo, si Número , Racional y Entero son tipos tales que Número  :>  Racional y Número  :>  Entero , una función escrita para tomar un Número funcionará igualmente bien cuando se le pase un Entero o Racional que cuando se le pase un Número . El tipo real del objeto se puede ocultar a los clientes en una caja negra y se puede acceder a él a través de la identidad del objeto . De hecho, si el tipo de Número es abstracto , es posible que ni siquiera sea posible poner sus manos en un objeto cuyoEl tipo más derivado es Número (ver tipo de datos abstracto , clase abstracta ). Este tipo particular de jerarquía de tipos se conoce, especialmente en el contexto del lenguaje de programación Scheme, como una torre numérica y, por lo general, contiene muchos más tipos.

Los lenguajes de programación orientados a objetos ofrecen polimorfismo de subtipo utilizando subclases (también conocido como herencia ). En implementaciones típicas, cada clase contiene lo que se llama una tabla virtual, una tabla de funciones que implementan la parte polimórfica de la interfaz de la clase, y cada objeto contiene un puntero a la "vtable" de su clase, que luego se consulta cada vez que un polimórfico se llama al método. Este mecanismo es un ejemplo de:

  • vinculación tardía , porque las llamadas a funciones virtuales no están vinculadas hasta el momento de la invocación;
  • envío único (es decir, polimorfismo de un solo argumento), porque las llamadas a funciones virtuales se enlazan simplemente mirando a través de la tabla v proporcionada por el primer argumento (elthisobjeto), por lo que los tipos de tiempo de ejecución de los otros argumentos son completamente irrelevantes.

Lo mismo ocurre con la mayoría de los otros sistemas de objetos populares. Algunos, sin embargo, como Common Lisp Object System , proporcionan envío múltiple , bajo el cual las llamadas a métodos son polimórficas en todos los argumentos.

La interacción entre polimorfismo paramétrico y subtipificación conduce a los conceptos de varianza y cuantificación acotada .

Polimorfismo de fila [ editar ]

El polimorfismo de fila [8] es un concepto similar, pero distinto, del subtipo. Se trata de tipos estructurales . Permite el uso de todos los valores cuyos tipos tienen determinadas propiedades, sin perder la información restante del tipo.

Politipismo [ editar ]

Un concepto relacionado es el politipismo (o genérico del tipo de datos ). Una función politípica es más general que polimórfica, y en tal función, "aunque se pueden proporcionar casos ad hoc fijos para tipos de datos específicos, no existe un combinador ad hoc". [9]

Aspectos de implementación [ editar ]

Polimorfismo estático y dinámico [ editar ]

El polimorfismo se puede distinguir por cuándo se selecciona la implementación: estáticamente (en tiempo de compilación) o dinámicamente (en tiempo de ejecución, normalmente a través de una función virtual ). Esto se conoce respectivamente como envío estático y envío dinámico , y las formas correspondientes de polimorfismo se denominan en consecuencia polimorfismo estático y polimorfismo dinámico .

El polimorfismo estático se ejecuta más rápido, porque no hay sobrecarga de despacho dinámico, pero requiere soporte adicional del compilador. Además, el polimorfismo estático permite un mayor análisis estático por parte de compiladores (especialmente para la optimización), herramientas de análisis de código fuente y lectores humanos (programadores). El polimorfismo dinámico es más flexible pero más lento; por ejemplo, el polimorfismo dinámico permite la escritura de pato y una biblioteca vinculada dinámicamente puede operar en objetos sin conocer su tipo completo.

El polimorfismo estático ocurre típicamente en polimorfismo ad hoc y polimorfismo paramétrico, mientras que el polimorfismo dinámico es usual para polimorfismo de subtipo. Sin embargo, es posible lograr polimorfismo estático con subtipificación mediante un uso más sofisticado de la metaprogramación de plantilla , es decir, el patrón de plantilla curiosamente recurrente .

Cuando el polimorfismo se expone a través de una biblioteca , el polimorfismo estático se vuelve imposible para las bibliotecas dinámicas, ya que no hay forma de saber qué tipos son los parámetros cuando se construye el objeto compartido . Mientras que lenguajes como C ++ y Rust usan plantillas monomorfizadas, el lenguaje de programación Swift hace un uso extensivo del envío dinámico para construir la interfaz binaria de la aplicación para estas bibliotecas de forma predeterminada. Como resultado, se puede compartir más código para un tamaño de sistema reducido a costa de la sobrecarga del tiempo de ejecución. [10]

Ver también [ editar ]

  • Tipificación de pato para polimorfismo sin tipos (estáticos)
  • Código polimórfico (terminología de virus informáticos)
  • Sistema F para un cálculo lambda con polimorfismo paramétrico.
  • Clase de tipo
  • Teoría de tipos
  • Herencia virtual

Referencias [ editar ]

  1. ^ Bjarne Stroustrup (19 de febrero de 2007). "Glosario de C ++ de Bjarne Stroustrup" . polimorfismo: proporciona una única interfaz a entidades de diferentes tipos.
  2. ^ a b c Cardelli, Luca ; Wegner, Peter (diciembre de 1985). "Sobre la comprensión de los tipos, la abstracción de datos y el polimorfismo" (PDF) . Encuestas de computación ACM . 17 (4): 471–523. CiteSeerX 10.1.1.117.695 . doi : 10.1145 / 6041.6042 . ISSN 0360-0300 .   : "Los tipos polimórficos son tipos cuyas operaciones son aplicables a valores de más de un tipo".
  3. ^ Booch, et al 2007 Diseño y análisis orientado a objetos con aplicaciones. Addison-Wesley.
  4. ^ Strachey, Christopher (2000). "Conceptos fundamentales en lenguajes de programación". Computación simbólica y de orden superior . 13 (1/2): 11–49. CiteSeerX 10.1.1.332.3161 . doi : 10.1023 / A: 1010000313106 . ISSN 1573-0557 .  
  5. ^ Christopher Strachey. Conceptos fundamentales en lenguajes de programación (PDF) . www.itu.dk . Editores académicos de Kluwer. Archivado desde el original (PDF) el 12 de agosto de 2017 . Consultado el 13 de octubre de 2012 .
  6. ^ Allen B. Tucker (28 de junio de 2004). Manual de informática, segunda edición . Taylor y Francis. págs. 91–. ISBN 978-1-58488-360-9.
  7. ^ Pierce, BC 2002 Tipos y lenguajes de programación. MIT Press.
  8. ^ Varita, Mitchell (junio de 1989). "Inferencia de tipos para concatenación de registros y herencia múltiple". Actas. Cuarto Simposio Anual de Lógica en Informática . págs. 92–97. doi : 10.1109 / LICS.1989.39162 .
  9. ^ Ralf Lammel y Joost Visser, "Combinadores mecanografiados para recorrido genérico", en Aspectos prácticos de los lenguajes declarativos: IV Simposio internacional (2002), p. 153.
  10. ^ Beingessner, Alexis. "Cómo Swift logró la vinculación dinámica donde Rust no pudo" .

Enlaces externos [ editar ]

  • Ejemplos de polimorfismo en C ++
  • Objetos y polimorfismo (prólogo visual)