¿Qué es la unión temprana y tardía?

77

Sigo escuchando acerca de la unión temprana y tardía, pero no entiendo lo que 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?

RATHOD DE SAMIR
fuente
1
tiempo de compilación vs tiempo de ejecución.
barlop
Aquí hay una buena lectura sobre el tema: en.wikibooks.org/wiki/Introduction_to_Programming_Languages/…
Jay Elston

Respuestas:

84

Hay dos conceptos principales en confusión: encuadernación y carga. Se combina con el concepto de enlace de datos, que se encuentra en algún punto intermedio a menudo haciendo ambas cosas. Después de considerarlo, voy a agregar un concepto más, para completar la trifecta, despacho.

Tipos

Enlace tardío : el tipo es desconocido hasta que la variable se ejerce durante el tiempo de ejecución; generalmente a través de la asignación, pero hay otros medios para forzar un tipo; los idiomas escritos dinámicamente llaman a esto una característica subyacente, pero muchos idiomas escritos estáticamente tienen algún método para lograr un enlace tardío

Implementado a menudo utilizando tipos dinámicos [especiales], introspección / reflexión, banderas y opciones de compilación, o mediante métodos virtuales al tomar prestado y extender el despacho dinámico

Enlace temprano : el tipo se conoce antes de que la variable se ejerza durante el tiempo de ejecución, generalmente a través de un medio estático y declarativo

Implementado a menudo utilizando tipos primitivos estándar

Las funciones

Despacho estático : función específica conocida o subrutina en tiempo de compilación; no es ambiguo y coincide con la firma

Implementado como funciones estáticas; ningún método puede tener la misma firma

Despacho dinámico : no es una función específica o subrutina en tiempo de compilación; determinado por el contexto durante la ejecución. Existen 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 la función adecuada.

En el envío único [ dinámico ] , solo se utiliza el tipo de instancia para determinar la implementación de la función adecuada. En lenguajes de tipo 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 la instancia del objeto, para inferir la implementación adecuada, este enfoque se denomina "despacho único".

También hay un despacho [ dinámico ] múltiple , donde los tipos de parámetros de entrada también ayudan a determinar qué implementación de función llamar. Debido a que los tipos múltiples, tanto el tipo de la instancia como el tipo (s) de los parámetros, influyen en la implementación del método seleccionado, este enfoque se denomina "despacho múltiple".

Implementado como funciones virtuales o abstractas; Otras pistas incluyen métodos anulados, ocultos u sombreados.

NB: si la sobrecarga de métodos implica o no un despacho dinámico 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 objeto que difiere la asignación de valor hasta que se necesite ; permite que un objeto esté en un estado esencialmente válido pero incompleto y esperando 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 deliberadamente una colección o lista en un objeto compuesto durante el constructor o las llamadas de inicialización hasta que una persona que llama aguas abajo solicita 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 de singleton bastante seguro y eficiente

Eager Loading : estrategia de inicialización de objetos que realiza inmediatamente todas las asignaciones de valores para tener todos los datos necesarios para completarse antes de considerarse en un estado válido.

Se implementa a menudo proporcionando objetos compuestos con todos sus datos conocidos lo antes posible, como durante una llamada o inicialización del constructor

Enlace de datos : a menudo implica crear un enlace o mapa activo 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 tienen que tener un tipo 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, ver modelo a ver, modelo a controlador, etc.) y habla sobre conceptos como origen y destino, puntos finales, vinculación / desvinculación, actualización y eventos como on_bind, on_property_change, on_explicit, on_out_of_scope


NOTA DE EDICIÓN: Última edición importante para proporcionar una descripción de ejemplos de cómo ocurren a menudo. Los ejemplos de código particulares dependen completamente de la implementación / tiempo de ejecución / plataforma

JustinC
fuente
2
Esta respuesta parece demasiado específica para los lenguajes orientados a objetos.
Jack
27

Cualquier cosa que el compilador decida mientras compila puede referirse a la vinculación EARLY / COMPILE TIME y cualquier cosa que se decida en RUNTIME se denomina vinculación LATE / RUNTIME .

Por ejemplo,

Método de sobrecarga y método de anulación .

1) En la sobrecarga de métodos, el compilador decide las llamadas a los métodos en el sentido de que el compilador decide qué función se llamará en el momento de la compilación. Por lo tanto, ser vinculante temprano .

2) En la anulación de métodos, en RUNTIME se decide qué método se llamará. Por lo que se reffered como el enlace en tiempo .

Intenté mantenerlo simple y fácil de conseguir. Espero que esto ayude.

trapaank
fuente
9

El enlace tardío es cuando el comportamiento se evalúa en tiempo de ejecución. Es necesario cuando realmente desea determinar cómo actuar basándose en la información que solo tiene cuando el programa se está ejecutando. El ejemplo más claro en mi opinión 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á void A::f(), porque está enlazado temprano (o estáticamente), por lo que el programa en tiempo de ejecución piensa que es solo un puntero a una Avariable de tipo, mientras a->g()que en realidad llamará void B::g(), porque el compilador, ver g()es virtual, inyecta código para mirar la dirección de la función correcta para llamar en tiempo de ejecución.

Ñame Marcovic
fuente
1
"El tiempo de ejecución"? Estás hablando de C ++. C ++ compila directamente al código de la máquina, no necesita tiempo de ejecución para resolver métodos virtuales.
tdammers 01 de
3
@tdammers C ++ realmente necesita una biblioteca de tiempo de ejecución, aunque no para llamadas virtuales. Si lee detenidamente, 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 independiente del tipo seguido de una llamada a la función. No hay "pensamiento" involucrado; la única razón por la que funciona de manera confiable es porque el compilador realiza la verificación de tipo 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 tipo. Si usa conversiones inseguras (por ejemplo , conversiones de puntero de estilo C), puede tratar legalmente los objetos C ++ como objetos de la clase incorrecta, pero sus archivos vtables estarán completamente desordenados y el código simplemente se rompe.
tdammers 01 de
@tdammers Intenté alejarme de ese tipo de respuesta, porque es un detalle de implementación de compiladores, que podría o no ser cierto para algún compilador esotérico. Lo que importa es el concepto.
Yam Marcovic
1
@tdammers Y por "el tiempo de ejecución" quiero decir "el programa en tiempo de ejecución". Obviamente, C ++ no se gestiona. Pero como me enseñaste que puede causar confusión, lo estoy cambiando a la redacción completa.
Yam Marcovic
5

Si está familiarizado con los punteros de función, este sería un ejemplo. Se puede decir que las funciones definidas son de enlace temprano. mientras que si utiliza 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á ligada en el compilador de enlace de tiempo)

pero el puntero de función se enlaza tarde, el fp puede llamar a add o sub dependiendo de la elección del usuario [en tiempo de ejecución].

Dineshkumar
fuente
3

El enlace temprano y tardío solo tiene sentido en el contexto de los tipos y no en la forma en que lo está describiendo. Casi todos los idiomas modernos están escritos en el sentido de que todos los valores tienen tipos fijos. La diferencia viene cuando miramos dinámicamente vs lenguajes tipados estáticamente. En los lenguajes de tipo dinámico, las variables no tienen tipos, por lo que pueden hacer referencia a valores de cualquier tipo y esto significa que cuando se llama 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 difiere hasta el último momento. La mayoría de las personas llaman a este estado de cosas vinculante tarde.

En un lenguaje de tipo estático, 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 supongamos que por ahora. Ahora, 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 al método es válida o no en tiempo de ejecución porque puede determinar la validez antes de que se ejecute el código. Esto se conoce como unión temprana.

Un ejemplo para demostrar la unión tardía en rubí:

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 arreglan en tiempo de ejecución.

davidk01
fuente
1

En lugar de darle una definición académica, intentaré mostrarle algunas de las diferencias usando un ejemplo del mundo real usando VBA:

Enlace temprano:

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 recibe un mensaje de error en el momento de la compilación cuando tiene un error tipográfico FileSystemObjecto 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 de la instancia y la determinación del tipo solo ocurrirán 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 de la encuadernación tardía es que no tiene ningún tipo de verificación fuerte aquí. Pero esa es también la ventaja: supongamos 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). El enlace tardío le permite escribir código que funciona junto con todas esas versiones: primero puede determinar la versión específica del componente y, si descubre que tiene solo una versión anterior disponible, evite ejecutar llamadas a funciones que no funcionan con esa versión.

Doc Brown
fuente
-2

Quizás el ejemplo más común de enlace tardío es resolver URL de Internet. Admite sistemas dinámicos y sistemas grandes sin tratar de vincular y vincular todos los sitios del mundo antes de que pueda acceder a ninguno, pero, por otro lado, incurre en una sobrecarga (búsqueda de DNS, mucho menos enrutamiento IP) en tiempo de ejecución.

Por esa luz, 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.

JRStern
fuente
¿Puede encontrar una referencia para esta definición de enlace? No he oído hablar de resolver direcciones de Internet como "vinculantes", aunque dado que la vinculación es el acto de resolver nombres, supongo que alguien ha argumentado que el concepto de vinculación temprana / tardía se puede aplicar a la resolución de URI a direcciones de Internet. Pero esta no es una interpretación común, y el concepto de enlace temprano / tardío es anterior al momento en que las computadoras estaban comúnmente conectadas a Internet.
Jay Elston