Cosè lassociazione anticipata e tardiva?
Su Novembre 18, 2020 da adminContinuo a sentire parlare di binding anticipato e tardivo, ma non capisco cosa siano. Ho trovato la seguente spiegazione che non capisco:
Lassociazione anticipata si riferisce allassegnazione di valori alle variabili durante la fase di progettazione mentre lassociazione tardiva si riferisce allassegnazione di valori alle variabili durante il tempo di esecuzione.
Qualcuno potrebbe definire i due tipi di associazione e confrontarli?
Commenti
- tempo di compilazione vs runtime.
- Ecco una buona lettura sullargomento: en.wikibooks.org/ wiki / Introduction_to_Programming_Languages / …
Answer
Ci sono due concetti principali in confusione: binding 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 la trifecta, invio.
Tipi
Rilegatura tardiva : il tipo è sconosciuto finché la variabile non viene esercitata durante il runtime; di solito tramite assegnazione ma ci sono altri mezzi per forzare un tipo; i linguaggi tipizzati dinamicamente chiamano questa caratteristica una caratteristica sottostante, ma molti linguaggi tipizzati staticamente hanno qualche metodo per ottenere lassociazione tardiva
Implementato spesso usando tipi dinamici [speciali], introspezione / riflessione, flag e opzioni del compilatore o attraverso metodi virtuali prendendo in prestito ed estendendo linvio dinamico
Early Binding : il tipo è noto prima che la variabile venga esercitata durante il runtime, di solito attraverso un mezzo statico e dichiarativo
Implementato spesso utilizzando tipi primitivi standard
Funzioni
Static Dispatch : funzione specifica nota o subroutine in fase di compilazione; non è ambiguo e corrisponde alla firma
Implementato 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 lesecuzione. Esistono due diversi approcci al “invio dinamico”, distinti da quali informazioni contestuali vengono utilizzate per selezionare limplementazione della funzione appropriata.
In singolo [ dinamico ] dispatch , viene utilizzato solo il tipo di istanza per determinare limplementazione 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 viene dichiarata / assegnata. Poiché viene utilizzato un solo tipo, il tipo dellistanza delloggetto, per dedurre limplementazione appropriata, questo approccio è chiamato “invio singolo”.
Esiste anche più [ dynamic ] dispatch , dove i tipi di parametri di input aiutano anche a determinare quale implementazione della funzione chiamare. Perché più tipi – sia il tipo di istanza e il tipo (i) del parametro (i) – influenzano quale implementazione del metodo è selezionata, questo approccio è soprannominato “invio multiplo”.
Implementato come funzioni virtuali o astratte; altri indizi includono metodi sostituiti, nascosti o nascosti.
NB: Il fatto che il sovraccarico dei metodi implichi o meno linvio dinamico dipende dal linguaggio. Ad esempio, in Java, i metodi sovraccaricati vengono inviati staticamente.
Valori
Lazy Loading : strategia di inizializzazione degli oggetti che differisce lassegnazione del valore fino a quando non è necessario ; consente a 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 grandi set di dati o in attesa di risorse esterne
Implementato spesso intenzionalmente non caricando una raccolta o un elenco in un oggetto composito durante le chiamate del costruttore o di inizializzazione fino a quando un chiamante a valle non chiede di vedere il contenuto di quella raccolta (es. get_value_at, get_all_as, ecc.).Le variazioni includono il caricamento di meta informazioni sulla raccolta (come la dimensione o le chiavi), ma lomissione dei dati effettivi; fornisce anche un meccanismo ad alcuni runtime per fornire agli sviluppatori uno schema di implementazione singleton abbastanza sicuro ed efficiente
Caricamento desideroso : strategia di inizializzazione degli oggetti che esegue immediatamente tutte le assegnazioni di valore in modo da avere tutti i dati necessari per essere completi prima di considerarsi in uno stato valido.
Implementato spesso da fornire un oggetto composito con tutti i dati noti il prima possibile, ad esempio durante una chiamata o uninizializzazione del costruttore
Associazione dati : spesso implica la creazione di un collegamento attivo o di una mappa tra due flussi di informazioni compatibili in modo che le modifiche a uno si riflettano nellaltro e viceversa; per essere compatibili, spesso devono avere un tipo di base o uninterfaccia comune
Implementato spesso come tentativo di fornire una sincronizzazione più pulita e coerente tra i diversi aspetti dellapplicazione (es. visualizzazione-modello per visualizzazione, modello per controller , ecc.) e parla di concetti come origine e destinazione, endpoint, bind / unbind, update ed eventi come on_bind, on_property_change, on_explicit, on_out_of_scope
NOTA EDIT: Ultima modifica principale per fornire la descrizione di esempi di come questi spesso si verificano. Alcuni esempi di codice dipendono interamente dallimplementazione / runtime / piattaforma
Commenti
- Questa risposta sembra troppo specifica per i linguaggi orientati agli oggetti.
- @Jack I don ‘ t mi sento in questo modo, penso che questo sia un ottimo che copre molti aspetti.
Risposta
Tutto ciò che viene deciso dal compilatore durante la compilazione può essere riferito a EARLY / COMPILE TIME Vincolante e tutto ciò che deve essere deciso a RUNTIME si chiama LATE / RUNTIME binding.
Ad esempio,
Metodo Overload e metodo Override .
1 ) In Method Overloading il tuo metodo chiama i metodi ar La decisione del compilatore nel senso che la funzione che verrà chiamata viene decisa dal compilatore in fase di compilazione. Quindi EARLY BINDING .
2) Nel metodo Overriding, viene deciso in RUNTIME quale metodo è sarà chiamato. Quindi è indicato come BINDING TARDIVO .
Ho cercato di mantenerlo semplice e facile da ottenere. Spero che questo aiuti.
Risposta
Lassociazione tardiva è quando il comportamento viene valutato in fase di esecuzione. È necessario quando si desidera effettivamente determinare come agire in base alle informazioni che si hanno solo quando il programma è in esecuzione. Lesempio più chiaro a mio avviso è il meccanismo delle funzioni virtuali, 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é è in anticipo (o staticamente ), quindi il programma in fase di esecuzione pensa di essere solo un puntatore a una variabile di tipo A
, mentre a->g()
chiamerà effettivamente void B::g()
, perché il compilatore, vedendo che g()
è virtuale, inserisce il codice per cercare lindirizzo della funzione corretta da chiamare in fase di esecuzione.
Commenti
- ” Il runtime “? ‘ stai parlando di C ++. C ++ compila direttamente in codice macchina, non ‘ non è necessario un runtime per risolverlo metodi virtuali.
- @tdammers C ++ in realtà ha bisogno di una libreria di runtime, sebbene non per le chiamate virtuali. Se leggi attentamente, ‘ noterai che questa risposta dice che il compilatore ” inserisce il codice per cercare lindirizzo della funzione corretta [ …] in runtime “.
- Bene, ma quel ” codice per cercare lindirizzo della funzione corretta ” è fondamentalmente solo una dereferenziazione del puntatore a due stadi indipendente dal tipo seguita da una chiamata di funzione. Nessun ” pensiero ” coinvolto; lunica ragione per cui funziona in modo affidabile è perché il compilatore esegue il controllo del tipo in fase di compilazione ; in fase di esecuzione, il codice generato confida che il compilatore abbia svolto i compiti di controllo del tipo. Se utilizzi cast non sicuri (ad es.Il puntatore in stile C esegue il cast), puoi trattare legalmente gli oggetti C ++ come oggetti della classe sbagliata, ma i loro vtable saranno completamente incasinati e il codice si rompe.
- @tdammers Ho cercato di stare lontano da questo tipo di risposta, perché ‘ è un dettaglio di implementazione dei compilatori, il che potrebbe o non potrebbe essere vero per alcuni compilatori esoterici. Ciò che conta è il concetto.
- @tdammers E per ” il runtime ” intendo ” il programma in fase di esecuzione “. Ovviamente il C ++ non è ‘ gestito. Ma poiché mi hai mostrato che può creare confusione, ‘ lo sto cambiando con il testo completo.
Risposta
se hai familiarità con i puntatori a funzione, questo sarebbe un esempio. Si può dire che le funzioni definite siano Early binding. mentre se si utilizzano i puntatori a funzione, il suo binding tardivo.
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 compilatore time-linker)
ma il puntatore alla funzione è in ritardo binding, lfp può chiamare add o sub a seconda della scelta dellutente [in fase di esecuzione].
Answer
Solo binding anticipato e tardivo ha senso nel contesto dei tipi e non nel modo in cui lo descrivi. Quasi tutti i linguaggi moderni sono digitati nel senso che tutti i valori hanno tipi fissi. La differenza arriva quando guardiamo i linguaggi tipizzati dinamicamente e staticamente. Nei linguaggi tipizzati dinamicamente le variabili non hanno tipi quindi possono riferirsi a valori di qualsiasi tipo e questo significa che quando chiami un metodo su un oggetto a cui fa riferimento una variabile lunico modo per determinare se quella chiamata è valida o meno è cercare loggetto nella classe e vedere se quel metodo esiste effettivamente. Ciò consente alcune cose interessanti come laggiunta di nuovi metodi alle classi in fase di esecuzione perché la ricerca del metodo effettivo viene rimandata fino allultimo momento. La maggior parte delle persone chiama questo stato di si occupa di late binding.
In un linguaggio tipizzato staticamente le variabili hanno dei tipi e una volta dichiarate non possono fare riferimento a nessun valore che non sia dello stesso tipo. Questo non è strettamente vero ma supponiamo che per ora. Ora, se sai che la variabile si riferirà solo a valori di un tipo specifico, non cè motivo di capire se una chiamata al metodo è valida o meno in fase di esecuzione perché puoi determinare la validità prima che il codice venga mai eseguito. Questo è indicato come associazione anticipata.
Un esempio per dimostrare lassociazione tardiva in 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 sequenza di azioni sopra non è possibile in un linguaggio come Java in cui tutti i tipi sono fissati in fase di esecuzione.
Answer
Invece di darti una definizione accademica, io proverà a mostrarti alcune delle differenze utilizzando un esempio del mondo reale utilizzando VBA:
Associazione anticipata:
Dim x As FileSystemObject Set x = New FileSystemObject Debug.Print x.GetSpecialFolder(0)
Ciò richiede limpostazione di un riferimento al componente “Microsoft Scripting Runtime” in progettazione . Ha il vantaggio di ricevere un messaggio di errore già in fase di compilazione quando si ha un errore di battitura in FileSystemObject
o nomi di metodi come GetSpecialFolder
.
Binding tardivo
Dim x As Object Set x = CreateObject("Scripting.FileSystemObject") Debug.Print x.GetSpecialFolder(0)
Ciò non richiede limpostazione anticipata di un riferimento, la creazione e il tipo dellistanza la determinazione avverrà solo in fase di esecuzione. Il compilatore non si lamenterà in fase di compilazione quando provi a chiamare un metodo inesistente di x
, questo porterà a un errore di runtime solo quando la riga specifica viene eseguita .
Quindi, lo svantaggio del binding tardivo è che qui non hai alcun controllo del tipo forte. Ma questo è anche il vantaggio: supponiamo che tu abbia 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 linterfaccia COM di Excel) Lassociazione tardiva consente scrivi codice che funziona insieme a tutte quelle versioni: puoi prima determinare la versione specifica del componente e, se scopri di avere solo una versione precedente disponibile, evita di eseguire chiamate di funzioni che non funzionano con quella versione.
Risposta
Forse lesempio più comune di associazione tardiva è la risoluzione degli URL Internet. Supporta sistemi dinamici e sistemi di grandi dimensioni senza cercare di collegare e associare ogni sito nel mondo prima che tu possa raggiungerne uno qualsiasi, ma daltra parte incorre in un certo sovraccarico (ricerca DNS, molto meno instradamento IP) in fase di esecuzione.
Alla luce di ciò, la maggior parte delle varietà di binding negli ambienti linguistici è più o meno precoce, al momento della compilazione o del collegamento.
Ogni tipo ha costi e benefici.
Commenti
- Potete trovare un riferimento nel sito per questa definizione di associazione?Non ho sentito parlare della risoluzione di indirizzi Internet come ” vincolante “, anche se dal momento che vincolare è latto di risolvere i nomi, suppongo che qualcuno abbia sostenuto che il concetto di associazione anticipata / tardiva può essere applicato alla risoluzione di URI a indirizzi Internet. Ma questa non è uninterpretazione comune e il concetto di associazione anticipata / tardiva precede il tempo in cui i computer erano comunemente connessi a Internet.
Lascia un commento