En programación orientada a objetos , la delegación se refiere a evaluar un miembro ( propiedad o método ) de un objeto (el receptor) en el contexto de otro objeto original (el remitente). La delegación se puede realizar explícitamente, pasando el objeto emisor al objeto receptor, lo que se puede realizar en cualquier lenguaje orientado a objetos ; o implícitamente, por las reglas de búsqueda de miembros del idioma, lo que requiere soporte de idioma para la característica. La delegación implícita es el método fundamental para la reutilización del comportamiento en la programación basada en prototipos , correspondiente a la herencia en la programación basada en clases . Los lenguajes más conocidos que admiten la delegación a nivel de lenguaje son Self , que incorpora la noción de delegación a través de su noción de ranuras principales mutables que se utilizan en la búsqueda de métodos en autollamadas, y JavaScript ; consulte delegación de JavaScript .
El término delegación también se utiliza libremente para otras relaciones entre objetos; consulte delegación (programación) para obtener más información. Conceptos que frecuentemente se confunden son simplemente el uso de otro objeto, más precisamente denominado consulta o agregación ; y evaluar un miembro en un objeto evaluando el miembro correspondiente en otro objeto, especialmente en el contexto del objeto receptor, lo que se conoce más precisamente como reenvío (cuando un objeto contenedor no se pasa al objeto envuelto). [1] [2] [a] El patrón de delegación es un patrón de diseño de software para implementar la delegación, aunque este término también se usa libremente para consulta o reenvío.
Lieberman definió este sentido de delegación como característica del lenguaje de programación que hace uso de las reglas de búsqueda de métodos para enviar las llamadas autollamadas en su artículo de 1986 "Uso de objetos prototípicos para implementar un comportamiento compartido en sistemas orientados a objetos".
La delegación depende del enlace dinámico , ya que requiere que una llamada a un método determinado pueda invocar diferentes segmentos de código en tiempo de ejecución [ cita requerida ] . Se utiliza en macOS (y su predecesor NeXTStep ) como una forma de personalizar el comportamiento de los componentes del programa. [3] Permite implementaciones como el uso de una única clase proporcionada por el sistema operativo para administrar Windows, porque la clase toma un delegado que es específico del programa y puede anular el comportamiento predeterminado según sea necesario. Por ejemplo, cuando el usuario hace clic en el cuadro de cierre, el administrador de ventanas envía al delegado una llamada windowShouldClose:, y el delegado puede retrasar el cierre de la ventana, si hay datos no guardados representados por el contenido de la ventana.
La delegación se puede caracterizar (y distinguir del reenvío ) como vinculación tardía de uno mismo : [4]
... los mensajes enviados a la variable
self
(othis
) en el padre "volverán" al objeto que recibió originalmente el mensaje.
Es decir, la self
definición de un método en el objeto receptor no está vinculada estáticamente a ese objeto en el momento de la definición (como en el momento de la compilación o cuando la función está adjunta a un objeto), sino que en el momento de la evaluación , está vinculada al original. objeto.
Se ha argumentado que en algunos casos puede preferirse la delegación a la herencia para hacer que el código del programa sea más legible y comprensible. [5] A pesar de que la delegación explícita está bastante extendida, relativamente pocos lenguajes de programación importantes implementan la delegación como modelo alternativo a la herencia. La relación precisa entre delegación y herencia es complicada; algunos autores los consideran equivalentes, o uno como un caso especial del otro. [6]
En los lenguajes que admiten la delegación mediante reglas de búsqueda de métodos, la distribución de métodos se define de la misma manera que se define para los métodos virtuales en herencia: siempre es el método más específico el que se elige durante la búsqueda de métodos. Por lo tanto, es la entidad receptora original la que inicia la búsqueda de métodos aunque haya pasado el control a algún otro objeto (a través de un enlace de delegación, no una referencia de objeto).
La delegación tiene la ventaja de que puede tener lugar en tiempo de ejecución y afectar sólo a un subconjunto de entidades de algún tipo e incluso puede eliminarse en tiempo de ejecución. La herencia, por el contrario, normalmente se dirige al tipo en lugar de a las instancias y está restringida al tiempo de compilación. Por otro lado, la herencia se puede verificar estáticamente, mientras que la delegación generalmente no puede hacerlo sin genéricos (aunque una versión restringida de la delegación puede ser estáticamente segura [7] ). La delegación puede denominarse "herencia en tiempo de ejecución para objetos específicos".
A continuación se muestra un ejemplo de pseudocódigo en un lenguaje similar a C# / Java :
class A { void foo () { // "esto" también se conoce con los nombres "actual", "yo" y "yo" en otros idiomas . bar (); } barra vacía () { imprimir ( "a.bar" ); } } clase B { delegado privado A a ; // enlace de delegación público B ( A a ) { este . una = una ; } vacío foo () { a . foo (); // llama a foo() en la instancia a } barra vacía () { imprimir ( "b.bar" ); } } a = nueva A (); b = nuevo B ( a ); // establecer delegación entre dos objetos
Al llamar, se b.foo()
imprimirá b.bar , ya que this
se refiere al objeto receptor originalb
, dentro del contexto de a
. La ambigüedad resultante this
se denomina esquizofrenia objetal .
Al traducir el parámetro implícito this
en un parámetro explícito, la llamada (en B
, con a
un delegado) a.foo()
se traduce en A.foo(b)
, utilizando el tipo de a
para la resolución del método, pero el objeto de delegación b
para el this
argumento.
Usando herencia, el código análogo (usando letras mayúsculas para enfatizar que la resolución se basa en clases, no en objetos) es:
clase A { void foo () { esto . bar (); } barra vacía () { imprimir ( "A.barra" ); } } clase B extiende A { public B () {} vacío foo () { super . foo (); // llama a foo() de la superclase (A) } barra vacía () { imprimir ( "B.barra" ); } } b = nuevo B ();
Llamar b.foo()
resultará en B.bar . En este caso, this
no es ambiguo: hay un único objeto, b
y this.bar()
se resuelve en el método de la subclase.
Los lenguajes de programación en general no admiten esta forma inusual de delegación como concepto de lenguaje, pero existen algunas excepciones [ cita requerida ] .
Si el lenguaje admite tanto la delegación como la herencia, se puede realizar una herencia dual utilizando ambos mecanismos al mismo tiempo como en
la clase C extiende A { delegationlink D d ; }
Esto requiere reglas adicionales para la búsqueda de métodos, ya que ahora hay potencialmente dos métodos que pueden denominarse como los más específicos (debido a las dos rutas de búsqueda).
La delegación puede describirse como un mecanismo de bajo nivel para compartir código y datos entre entidades. Por tanto, sienta las bases para otras construcciones del lenguaje. En particular, los lenguajes de programación orientados a roles han estado utilizando la delegación, pero especialmente los más antiguos utilizaron la agregación mientras afirmaban utilizar la delegación. Esto no debe considerarse una trampa, sino simplemente las definiciones plurales de lo que significa delegación (como se describe anteriormente).
Más recientemente, también se ha trabajado en la distribución de la delegación, de modo que, por ejemplo, los clientes de un motor de búsqueda (que encuentran habitaciones de hotel baratas) puedan utilizar una entidad compartida utilizando la delegación para compartir los mejores resultados y la funcionalidad general reutilizable.
Ernst y Lorenz también sugirieron la delegación para la resolución de consejos en programación orientada a aspectos en 2003.
Distinguir:
Este artículo propone la herencia basada en objetos (también conocida como delegación) como complemento a la composición de objetos puramente basada en reenvío. Presenta una integración segura de tipos de delegación en un modelo de objetos basado en clases y muestra cómo supera los problemas que enfrenta la interacción de componentes basada en reenvío, cómo admite la extensibilidad independiente de los componentes y la adaptación dinámica e imprevista de los componentes.
{{cite book}}
: Mantenimiento CS1: bot: estado de la URL original desconocido ( enlace ){{cite book}}
: |journal=
ignorado ( ayuda )Mantenimiento CS1: falta la ubicación del editor ( enlace )