Che cos'è l'associazione anticipata e tardiva?

75

Continuo a sentire legami precoci e tardivi, ma non capisco cosa siano. Ho trovato la seguente spiegazione che non capisco:

Early binding refers to assignment of values to variables during design time whereas late binding refers to assignment of values to variables during run time.

Qualcuno potrebbe definire i due tipi di associazione e confrontarli?

    
posta SAMIR RATHOD 01.06.2013 - 07:00
fonte

7 risposte

82

Ci sono due concetti principali in confusione: associazione e caricamento. È confuso dal concetto di DataBinding, che è da qualche parte nel mezzo che spesso fa entrambe le cose. Dopo averlo considerato, aggiungerò un altro concetto, per completare il trifecta, invio.

Tipi

Late Binding : type è sconosciuto fino a quando la variabile non viene esercitata durante l'esecuzione; di solito attraverso l'incarico ma ci sono altri mezzi per costringere un tipo; le lingue digitate dinamicamente chiamano questa una funzione sottostante, ma molte lingue tipizzate staticamente hanno un metodo per ottenere l'associazione tardiva

Implementati spesso usando [speciali] tipi dinamici, introspection / reflection, flag e opzioni del compilatore, o attraverso metodi virtuali prendendo in prestito ed estendendo il dispatch dinamico

Early Binding : tipo è noto prima che la variabile venga esercitata durante l'esecuzione, solitamente attraverso mezzi statici e dichiarativi

Implementato spesso usando tipi primitivi standard

Funzioni

Invio statico : funzione specifica nota o subroutine in fase di compilazione; non è ambiguo e corrisponde alla firma

Implementati come funzioni statiche; nessun metodo può avere la stessa firma

Dynamic Dispatch : non una funzione specifica o subroutine in fase di compilazione; determinato dal contesto durante l'esecuzione. Esistono due diversi approcci a "dispacciamento dinamico", distinti da quali informazioni contestuali vengono utilizzate per selezionare l'implementazione della funzione appropriata.

In singolo [ dinamico ] dispatch , viene utilizzato solo il tipo di istanza per determinare l'implementazione della funzione appropriata. Nei linguaggi tipizzati staticamente, ciò significa in pratica che il tipo di istanza decide quale implementazione del metodo viene utilizzata indipendentemente dal tipo di riferimento indicato quando la variabile è dichiarata / assegnata. Poiché solo un singolo tipo, il tipo di istanza dell'oggetto, viene utilizzato per dedurre l'implementazione appropriata, questo approccio è chiamato "invio singolo".

C'è anche multiplo [ dinamico ] dispatch , dove i tipi di parametri di input aiutano anche a determinare quale implementazione di funzione chiamare. Poiché più tipi - sia il tipo dell'istanza e il / i tipo / i dei parametri - influenzano l'implementazione del metodo, questo approccio è soprannominato "invio multiplo".

Implementate come funzioni virtuali o astratte; altri indizi includono metodi sottoposti a override, nascosti o ombreggiati.

NB: Indipendentemente dal fatto che l'overloading del metodo implichi l'invio dinamico è specifico della lingua. Ad esempio, in Java, i metodi sovraccaricati vengono inviati staticamente .

Valori

Caricamento lento : strategia di inizializzazione dell'oggetto che rimuove l'assegnazione del valore fino al necessario ; consente ad un oggetto di essere in uno stato essenzialmente valido ma consapevolmente incompleto e di attendere che i dati siano necessari prima di caricarlo; spesso trovato particolarmente utile per caricare dataset di grandi dimensioni o in attesa di risorse esterne

Spesso implementato non caricando intenzionalmente una raccolta o un elenco in un oggetto composito durante le chiamate di inizializzazione o di costruzione fino a quando un chiamante downstream chiede di vedere il contenuto di tale raccolta (ad esempio get_value_at, get_all_as, ecc.). Le varianti includono il caricamento delle meta informazioni sulla collezione (come le dimensioni o le chiavi), ma omettendo i dati reali; fornisce anche un meccanismo per alcuni runtime per fornire agli sviluppatori uno schema di implementazione singleton abbastanza sicuro ed efficiente

Caricamento Eager : strategia di inizializzazione dell'oggetto che esegue immediatamente tutte le assegnazioni di valori per avere tutti i dati necessari per essere completo prima di considerarsi in uno stato valido.

Implementato spesso fornendo un oggetto composito con tutti i dati noti il prima possibile, come durante una chiamata del costruttore o l'inizializzazione

Associazione dati : spesso comporta la creazione di un collegamento attivo o di una mappa tra due flussi di informazioni compatibili in modo che le modifiche a una siano riflesse nell'altra e viceversa; per essere compatibili, spesso devono avere un tipo di base comune, o un'interfaccia

Implementato spesso come tentativo di fornire una sincronizzazione più chiara e coerente tra i diversi aspetti applicativi (es. view-model to view, model to controller, ecc.) e parla di concetti come source e target, endpoint, binding / unbind, update, ed eventi come on_bind, on_property_change, on_explicit, on_out_of_scope

MODIFICA NOTA: Ultima modifica principale per fornire una descrizione degli esempi di come si verificano spesso. Esempi di codice particolari dipendono interamente dall'implementazione / runtime / piattaforma

    
risposta data 01.06.2013 - 08:32
fonte
26

Tutto ciò che viene deciso dal compilatore durante la compilazione può fare riferimento a EARLY / COMPILE TIME Binding e tutto ciò che deve essere deciso in RUNTIME viene chiamato LATE / RUNTIME vincolante.

Ad esempio,

Metodo Sovraccarico e Metodo Overriding .

1) In Sovraccarico di metodi le chiamate del metodo ai metodi vengono decise dal compilatore nel senso che la funzione che verrà chiamata viene decisa dal compilatore in fase di compilazione. Quindi essere BINDING EARLY .

2) Nel metodo Override, viene deciso in RUNTIME quale metodo verrà chiamato. Quindi è definito come LATE BINDING .

Ho cercato di renderlo semplice e facile da ottenere. Spero che questo aiuti.

    
risposta data 01.06.2013 - 08:36
fonte
9

L'associazione tardiva è quando il comportamento viene valutato in fase di runtime. È necessario quando si desidera effettivamente determinare come agire in base alle informazioni che si hanno solo quando il programma è in esecuzione. L'esempio più chiaro a mio avviso è il meccanismo della funzione virtuale, in particolare in 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();
}

In questo esempio, a->f() chiamerà effettivamente void A::f() , perché è presto (o staticamente) legato, e quindi il programma in fase di esecuzione pensa è solo un puntatore a un tipo A variabile, mentre a->g() chiamerà effettivamente void B::g() , perché il compilatore, vedendo g() è virtuale, inietta il codice per cercare l'indirizzo della funzione corretta da chiamare in fase di runtime.

    
risposta data 01.06.2013 - 07:57
fonte
5

se hai familiarità con i puntatori di funzione questo sarebbe un esempio. Le funzioni definite possono essere considerate vincolanti. mentre se usi i puntatori di funzione è in ritardo.

  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);
    }

qui le funzioni add e sub sono funzioni (il suo indirizzo è associato al compiler time-linker)

ma il puntatore della funzione è in ritardo con il binding che l'fp può chiamare add o sub a seconda della scelta dell'utente [al runtime].

    
risposta data 01.06.2013 - 07:05
fonte
3

L'associazione anticipata e tardiva ha senso solo nel contesto dei tipi e non nel modo in cui la descrivi. Praticamente tutti i linguaggi moderni sono tipizzati nel senso che tutti i valori hanno tipi fissi. La differenza arriva quando guardiamo dinamicamente rispetto alle lingue tipizzate staticamente. Nelle variabili di tipo dinamicamente tipizzate le variabili non hanno tipi in modo che possano riferirsi a valori di qualsiasi tipo e questo significa che quando si chiama un metodo su un oggetto a cui fa riferimento una variabile l'unico modo per determinare se quella chiamata è valida o meno è cercare la classe per l'oggetto e vedere se quel metodo esiste realmente. Ciò consente alcune cose interessanti come l'aggiunta di nuovi metodi alle classi in fase di esecuzione perché la ricerca effettiva del metodo viene posticipata fino all'ultimo momento. La maggior parte delle persone chiama questo stato di cose in ritardo vincolante.

In un linguaggio con caratteri statici le variabili hanno tipi e una volta dichiarato non può riferirsi a nessun valore che non sia dello stesso tipo. Questo non è strettamente vero, ma lascia supporre per ora. Ora, se si sa che la variabile si riferirà solo ai valori di un tipo specifico, non vi è alcun motivo per capire se una chiamata al metodo è valida o meno in fase di esecuzione perché è possibile determinare la validità prima che il codice venga mai eseguito. Questo è indicato come associazione anticipata.

Un esempio per dimostrare il legame tardivo nel rubino:

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 precedente sequenza di azioni non è possibile in una lingua come Java, in cui tutti i tipi sono corretti in fase di esecuzione.

    
risposta data 01.06.2013 - 07:47
fonte
1

Invece di darti una definizione accademica proverò a mostrarti alcune delle differenze usando un esempio reale usando VBA:

Associazione anticipata:

Dim x As FileSystemObject
Set x = New FileSystemObject
Debug.Print x.GetSpecialFolder(0)

Ciò richiede che un riferimento sia impostato sul componente "Microsoft Scripting Runtime" in tempo di progettazione . Ha il vantaggio di ricevere un messaggio di errore già al momento della compilazione quando hai un errore di battitura in FileSystemObject o nomi di metodi come GetSpecialFolder .

Associazione tardiva

Dim x As Object
Set x = CreateObject("Scripting.FileSystemObject")
Debug.Print x.GetSpecialFolder(0)

Questo non richiede un riferimento da impostare in anticipo, la creazione dell'istanza e la determinazione del tipo avverranno solo in fase di esecuzione. Il compilatore non si lamenterà in fase di compilazione quando si tenta di chiamare un metodo inesistente di x , questo porterà a un errore di run-time solo quando viene eseguita la linea specifica.

Quindi, lo svantaggio dell'etichettatura tardiva è che non hai alcun controllo di tipo strong qui. Ma questo è anche il vantaggio - diciamo che hai un componente in cui esistono diverse versioni e ogni versione più recente fornisce alcune funzioni aggiuntive. (Un esempio reale sono i componenti di MS Office, come l'interfaccia COM di Excel) Il binding tardivo consente di scrivere codice che funziona insieme a tutte quelle versioni: è possibile determinare prima la versione del componente specifico e, se si scopre di avere solo una versione precedente disponibile, evita di eseguire chiamate di funzioni che non funzionano con quella versione.

    
risposta data 01.06.2013 - 10:27
fonte
-2

Forse l'esempio più comune di associazione tardiva è la risoluzione degli URL di Internet. Supporta sistemi dinamici e sistemi di grandi dimensioni senza tentare di collegare e collegare tutti i siti del mondo prima di poterli raggiungere, ma d'altra parte comporta un sovraccarico (ricerca DNS, molto meno il routing IP) in fase di runtime.

Da quella luce, la maggior parte delle varietà di binding negli ambienti linguistici è più o meno precoce, in fase di compilazione o di collegamento.

Ogni tipo ha costi e benefici.

    
risposta data 17.01.2016 - 22:48
fonte

Leggi altre domande sui tag