¿Qué es la vinculación anticipada y tardía?
On noviembre 18, 2020 by adminSigo escuchando acerca de la vinculación temprana y tardía, pero no entiendo qué son. Encontré la siguiente explicación que no entiendo:
El enlace temprano se refiere a la asignación de valores a las variables durante el tiempo de diseño, mientras que el enlace tardío se refiere a la asignación de valores a las variables durante el tiempo de ejecución.
¿Podría alguien definir los dos tipos de enlace y compararlos?
Comentarios
- tiempo de compilación vs tiempo de ejecución.
- Aquí hay una buena lectura sobre el tema: en.wikibooks.org/ wiki / Introduction_to_Programming_Languages / …
Responder
Hay dos conceptos principales en confusión: encuadernación y carga. Se combina con el concepto de DataBinding, que se encuentra en algún lugar intermedio y suele hacer ambos. Después de considerarlo, voy a agregar un concepto más, para completar la trifecta, dispatch.
Tipos
Late Binding : el tipo es desconocido hasta que la variable se ejercita durante el tiempo de ejecución; generalmente mediante asignación, pero existen otros medios para coaccionar a un tipo; Los lenguajes de tipado dinámico llaman a esto una característica subyacente, pero muchos lenguajes de tipado estático tienen algún método para lograr un enlace tardío
Implementado a menudo usando tipos dinámicos [especiales], introspección / reflexión, banderas y opciones de compilador, o mediante métodos virtuales tomando prestado y extendiendo el envío dinámico
Enlace anticipado : tipo es conocido antes de que la variable se ejercite durante el tiempo de ejecución, generalmente a través de un medio declarativo estático
Se implementa a menudo usando tipos primitivos estándar
Funciones
Envío estático : función específica conocida o subrutina en tiempo de compilación; es inequívoco y se corresponde con la firma
Implementado como funciones estáticas; ningún método puede tener la misma firma
Dynamic Dispatch : no es una función específica o subrutina en tiempo de compilación; determinado por el contexto durante la ejecución. Hay dos enfoques diferentes para el «despacho dinámico», que se distinguen por la información contextual que se utiliza para seleccionar la implementación de función adecuada.
En solo [ dinámico ] dispatch , solo se utiliza el tipo de instancia para determinar la implementación de la función adecuada. En los lenguajes de tipado estático, lo que esto significa en la práctica es que el tipo de instancia decide qué implementación de método se usa independientemente del tipo de referencia indicado cuando se declara / asigna la variable. Debido a que solo se usa un solo tipo, el tipo de instancia de objeto, para inferir la implementación adecuada, este enfoque se denomina «envío único».
También hay múltiples [ dinámico ] despacho , donde los tipos de parámetros de entrada también ayudan a determinar qué implementación de función llamar. Porque varios tipos, tanto el tipo de instancia como los tipos de los parámetros, influyen qué implementación de método se selecciona, este enfoque se denomina «envío múltiple».
Implementado como funciones virtuales o abstractas; otras pistas incluyen métodos anulados, ocultos o sombreados.
NB: Si la sobrecarga de métodos implica el envío dinámico o no es específico del idioma. Por ejemplo, en Java, los métodos sobrecargados se envían estáticamente.
Valores
Carga diferida : estrategia de inicialización de objetos que difiere la asignación de valor hasta que se necesite ; permite que un objeto esté en un estado esencialmente válido pero conscientemente incompleto y que espere hasta que se necesiten los datos antes de cargarlo; a menudo se encuentra particularmente útil para cargar grandes conjuntos de datos o esperar recursos externos
Se implementa a menudo al no cargar intencionalmente una colección o lista en un objeto compuesto durante las llamadas al constructor o de inicialización hasta que algún llamador en sentido descendente solicite ver el contenido de esa colección (por ejemplo, get_value_at, get_all_as, etc.).Las variaciones incluyen cargar metainformación sobre la colección (como tamaño o claves), pero omitir los datos reales; también proporciona un mecanismo para algunos tiempos de ejecución para proporcionar a los desarrolladores un esquema de implementación singleton bastante seguro y eficiente
Carga ansiosa : estrategia de inicialización de objetos que realiza inmediatamente todas las asignaciones de valores para tener todos los datos necesarios para estar completos antes de considerarse en un estado válido.
Implementado a menudo por proporcionar objetos compuestos con todos sus datos conocidos lo antes posible, como durante una llamada o inicialización de un constructor
Enlace de datos : a menudo implica la creación de un enlace activo o mapa entre dos flujos de información compatibles para que los cambios en uno se reflejen en el otro y viceversa; para ser compatibles, a menudo deben tener un tipo de base común, o interfaz
Se implementa a menudo como un intento de proporcionar una sincronización más limpia y consistente entre diferentes aspectos de la aplicación (por ejemplo, vista-modelo a vista, modelo a controlador , etc.) y habla sobre conceptos como origen y destino, puntos finales, vincular / desvincular, actualizar y eventos como on_bind, on_property_change, on_explicit, on_out_of_scope
EDITAR NOTA: Última edición importante para proporcionar una descripción de ejemplos de cómo estos ocurren a menudo. Los ejemplos de código particulares dependen completamente de la implementación / tiempo de ejecución / plataforma
Comentarios
- Esta respuesta parece demasiado específica para lenguajes orientados a objetos.
- @Jack No ‘ no me siento así, creo que este es un excelente que cubre muchos aspectos.
Respuesta
Todo lo que decida el compilador durante la compilación puede consultarse en TIEMPO TEMPRANO / DE COMPILACIÓN La vinculación y cualquier cosa que se decida en RUNTIME se llama LATE / RUNTIME vinculante.
Por ejemplo,
Método Sobrecarga y método Anula .
1 ) En Sobrecarga de métodos , sus llamadas de métodos a los métodos ar Lo decide el compilador en el sentido de que el compilador decide qué función se va a llamar en el momento de la compilación. Por lo tanto, es EARLY BINDING .
2) En el método Overriding, se decide en RUNTIME qué método es va a ser llamado. Por lo tanto, se denomina VINCULACIÓN TARDÍA .
Intenté mantenerlo simple y fácil de obtener. Espero que esto ayude.
Respuesta
La vinculación tardía es cuando el comportamiento se evalúa en tiempo de ejecución. Es necesario cuando realmente desea determinar cómo actuar en función de la información que solo tiene cuando el programa se está ejecutando. En mi opinión, el ejemplo más claro es el mecanismo de función virtual, específicamente en C ++.
class A { public: void f() {} virtual void g() {} }; class B : public A { void f() {} virtual void g() {} }; int main() { A* a = new B; a->f(); a->g(); }
En este ejemplo, a->f()
realmente llamará a void A::f()
, porque es temprano (o estáticamente ) vinculado, por lo que el programa en tiempo de ejecución piensa que «es solo un puntero a una variable de tipo A
, mientras que a->g()
realmente llamará a void B::g()
, porque el compilador, viendo g()
es virtual, inyecta código para buscar la dirección de la función correcta para llamar en tiempo de ejecución.
Comentarios
- » El tiempo de ejecución «? Estás ‘ hablando de C ++. C ++ se compila directamente en código de máquina, no ‘ t necesita un tiempo de ejecución para resolver métodos virtuales.
- @tdammers C ++ realmente necesita una biblioteca de tiempo de ejecución, aunque no para llamadas virtuales. Si lee con atención, ‘ notará que esta respuesta dice que el compilador » inyecta código para buscar la dirección de la función correcta [ …] en tiempo de ejecución «.
- Bueno, pero ese » código para buscar la dirección de la función correcta » es básicamente una desreferencia de puntero de dos etapas agnóstica de tipo seguida de una llamada a función. No hay » pensamiento » involucrado; la única razón por la que funciona de forma fiable es porque el compilador realiza la comprobación de tipos en tiempo de compilación ; en tiempo de ejecución, el código generado confía en que el compilador haya realizado la tarea de verificación de tipos. Si usa yesos inseguros (p. Ej.Conversiones de punteros de estilo C), puede tratar legalmente los objetos C ++ como objetos de la clase incorrecta, pero sus vtables se estropearán por completo y el código simplemente se romperá.
- @tdammers Traté de mantenerme alejado de ese tipo de respuesta, porque ‘ es un detalle de implementación de los compiladores, lo que podría ser cierto o no para algún compilador esotérico. Lo que importa es el concepto.
- @tdammers Y por » el tiempo de ejecución » quiero decir » el programa en tiempo de ejecución «. Obviamente, C ++ no está ‘ t administrado. Pero como me mostró que puede causar confusión, ‘ lo estoy cambiando a la redacción completa.
Respuesta
Si está familiarizado con los punteros de función, este sería un ejemplo. Se puede decir que las funciones definidas son de enlace anticipado. mientras que si usa punteros de función, su enlace tardío.
int add(int x,int y) { return x+y; } int sub(int x,int y) { return x-y; } int main() { //get user choice int(*fp)(int,int); //if add fp=add; //else if sub fp=sub; cout<<fp(2,2); }
aquí las funciones add y sub son funciones (su dirección está enlazada en el tiempo de compilación-linker)
pero el puntero de función llega tarde enlazar el fp puede llamar a add o sub dependiendo de la elección del usuario [en tiempo de ejecución].
Responder
Solo enlace temprano y tardío tiene sentido en el contexto de los tipos y no en la forma en que lo describe. Casi todos los lenguajes modernos se escriben en el sentido de que todos los valores tienen tipos fijos. La diferencia surge cuando miramos los lenguajes tipados dinámicamente frente a los de tipo estático. En los lenguajes tipados dinámicamente, las variables no tienen tipos, por lo que pueden referirse a valores de cualquier tipo y esto significa que cuando llamas a un método en un objeto al que hace referencia alguna variable, la única forma de determinar si esa llamada es válida o no es busque la clase para el objeto y vea si ese método realmente existe. Esto permite algunas cosas interesantes como agregar nuevos métodos a las clases en tiempo de ejecución porque la búsqueda del método real se aplaza hasta el último momento. La mayoría de la gente llama a este estado de asuntos vinculantes tardíamente.
En un lenguaje tipado estáticamente, las variables tienen tipos y una vez declaradas no pueden hacer referencia a ningún valor que no sea del mismo tipo. Esto no es estrictamente cierto, pero asumámoslo por ahora. Ahora bien, si sabe que la variable solo se referirá a valores de un tipo específico, entonces no hay razón para averiguar si una llamada a un método es válida o no en el tiempo de ejecución porque puede determinar la validez antes de que se ejecute el código. Esto se conoce como enlace temprano.
Un ejemplo para demostrar el enlace tardío en ruby:
a = 1 # a is an integer at this point a.succ # asking for its successor is valid class A def method_a # some code end end a = A.new a.method_a # this is also valid a.succ # this is not valid class A # we can re-open the class and add a method def succ # some more code end end a.succ # now this is valid
La secuencia de acciones anterior no es posible en un lenguaje como Java, donde todos los tipos se fijan en tiempo de ejecución.
Respuesta
En lugar de darle una definición académica, intentará mostrarle algunas de las diferencias usando un ejemplo del mundo real usando VBA:
Enlace anticipado:
Dim x As FileSystemObject Set x = New FileSystemObject Debug.Print x.GetSpecialFolder(0)
Esto requiere que se establezca una referencia al componente «Microsoft Scripting Runtime» en tiempo de diseño . Tiene la ventaja de que ya aparece un mensaje de error en el momento de la compilación cuando tiene un error tipográfico en FileSystemObject
o nombres de métodos como GetSpecialFolder
.
Enlace tardío
Dim x As Object Set x = CreateObject("Scripting.FileSystemObject") Debug.Print x.GetSpecialFolder(0)
Esto no requiere que se establezca una referencia de antemano, la creación y el tipo de instancia la determinación ocurrirá en tiempo de ejecución. El compilador no se quejará en tiempo de compilación cuando intente llamar a un método inexistente de x
, esto conducirá a un error en tiempo de ejecución solo cuando se ejecute la línea específica .
Por lo tanto, la desventaja del enlace tardío es que aquí no tiene ninguna verificación de tipo sólida. Pero esa también es la ventaja: digamos que tiene un componente donde existen varias versiones, y cada versión más nueva proporciona algunas funciones adicionales. (Un ejemplo del mundo real son los componentes de MS Office, como la interfaz COM de Excel). escribe código que funciona junto con todas esas versiones; primero puede determinar la versión específica del componente, y si descubre que solo tiene una versión anterior disponible, evite ejecutar llamadas a funciones que no funcionan con esa versión.
Respuesta
Quizás el ejemplo más común de enlace tardío sea la resolución de URL de Internet. Es compatible con sistemas dinámicos y grandes sistemas sin intentar vincular y vincular todos los sitios del mundo antes de que pueda llegar a ninguno, pero por otro lado, genera algunos gastos generales (búsqueda de DNS, mucho menos enrutamiento de IP) en tiempo de ejecución.
A la luz de eso, la mayoría de las variedades de enlace en entornos de lenguaje es más o menos temprano, en tiempo de compilación o tiempo de enlace.
Cada tipo tiene costos y beneficios.
Comentarios
- ¿Puede encontrar una referencia para esta definición de encuadernación?No he oído hablar de resolver direcciones de Internet como » vinculantes «, aunque como vincular es el acto de resolver nombres, supongo que alguien ha argumentado que el concepto de enlace temprano / tardío se puede aplicar a la resolución de URI en direcciones de Internet. Pero esta no es una interpretación común, y el concepto de enlace temprano / tardío es anterior a la época en que las computadoras estaban comúnmente conectadas a Internet.
Deja una respuesta