Statico / dinamico vs forte / debole


319

Vedo questi termini fasciati dappertutto nella programmazione e ho una vaga idea di cosa significhino. Una ricerca mi mostra che tali cose sono state effettivamente chiuse in tutto lo stack overflow. Per quanto ne so, la tipizzazione statica / dinamica nelle lingue è leggermente diversa dalla tipizzazione forte / debole, ma ciò che questa differenza mi sfugge. Fonti diverse sembrano usare significati diversi o addirittura usare i termini in modo intercambiabile. Non riesco a trovare un posto che parli di entrambi e che spieghi effettivamente la differenza. Sarebbe bello se qualcuno potesse per favore spiegarlo chiaramente qui per me e per il resto del mondo.



Risposte:


423
  • La tipizzazione statica / dinamica riguarda quando vengono acquisite le informazioni sul tipo (sia in fase di compilazione che in fase di esecuzione)

  • La tipizzazione forte / debole riguarda la distinzione rigorosa dei tipi (ad es. Se la lingua tenta di eseguire una conversione implicita da stringhe a numeri).

Vedi la pagina wiki per informazioni più dettagliate.


7
Wikipedia ha tutte le risposte. Perché non mi sono già imbattuto in questo, non lo so.
Dan Revell,

31
È un peccato che molti non siano consapevoli del fatto che statico / dinamico è qualcosa di più che forte / debole ... Salverebbe davvero un po 'di parzialità e discussione.
Dykam,

10
Esistono diversi gradi di "debolezza del tipo". Un linguaggio fortemente tipizzato potrebbe tentare conversioni da stringhe a numeri. D'altra parte, HyperTalk (una lingua che ho usato decenni fa) era così debolmente tipizzato che "12" + "34"sarebbe uguale "46", ma "12" + "34Q"sarebbe uguale "1234Q"[per fortuna, si potrebbe scrivere "12" & "34"se si volesse concatenare]. Curiosamente, le variabili che contenevano numeri li memorizzavano come float a doppia precisione e la matematica su tali variabili utilizzava i valori in virgola mobile senza il munging delle stringhe, ma non c'era modo di chiedere se una variabile fosse una stringa o un numero.
supercat

9
@kittylyst Non riesco a vedere dove questa risposta suggerisca che forte sia sinonimo di statico
Pete

4
++ per (approssimativamente) definizioni a linea singola.
JamesFaix,

211

Hai scoperto un punto debole nella terminologia che i dilettanti usano per parlare di linguaggi di programmazione. Non usare i termini "forte" e "debole" , perché non hanno un significato tecnico universalmente concordato. Al contrario, la digitazione statica significa che i programmi vengono controllati prima di essere eseguiti e un programma potrebbe essere rifiutato prima di avviarsi. La digitazione dinamica significa che i tipi di valori vengono controllati durante l' esecuzione e un'operazione tipizzata male può causare l'interruzione del programma o la segnalazione di un errore in fase di esecuzione . Un motivo principale per la tipizzazione statica è di escludere i programmi che potrebbero avere tali "errori di tipo dinamico".

La tipizzazione forte generalmente significa che non ci sono scappatoie nel sistema dei tipi, mentre la tipizzazione debole significa che il sistema dei tipi può essere sovvertito (invalidando qualsiasi garanzia). I termini vengono spesso utilizzati in modo errato per indicare la digitazione statica e dinamica. Per vedere la differenza, pensa a C: il linguaggio è controllato dal tipo al momento della compilazione (tipizzazione statica), ma ci sono molte lacune; puoi praticamente lanciare un valore di qualsiasi tipo su un altro tipo della stessa dimensione --- in particolare, puoi lanciare liberamente i tipi di puntatore. Pascal era una lingua che doveva essere fortemente tipizzata, ma notoriamente aveva una scappatoia imprevista: un disco variante senza etichetta.

Le implementazioni di linguaggi fortemente tipizzati spesso acquisiscono scappatoie nel tempo, di solito in modo che parte del sistema di runtime possa essere implementato nella lingua di alto livello. Ad esempio, Objective Caml ha una funzione chiamata Obj.magicche ha l'effetto di runtime di restituire semplicemente il suo argomento, ma in fase di compilazione converte un valore di qualsiasi tipo in uno di qualsiasi altro tipo. Il mio esempio preferito è Modula-3, i cui designer hanno chiamato il loro costrutto per la fusione dei caratteri LOOPHOLE.

Detto questo, non puoi contare su due persone che usano le parole "forte" e "debole" esattamente allo stesso modo. Quindi evitali.


31
(+1) per il tuo suggerimento di evitare i termini "forte" e "debole".
Nico,

1
D'accordo, stava solo leggendo il libro di Jon Skeet, e questa è la stessa risposta annotata lì.
Bennett Yeates,

Per quanto ne so, Java ha anche queste scappatoie, ma è ancora considerato un linguaggio fortemente tipizzato, quindi immagino che questo dia più peso ai tuoi consigli per evitare i termini "forte" e "debole".
doubleOrt

74

In poche parole: in una lingua tipicamente statica il tipo è statico , il che significa che una volta impostata una variabile su un tipo, NON PUOI cambiarla. Questo perché la digitazione è associata alla variabile anziché al valore a cui si riferisce.

Ad esempio in Java:

String str = "Hello";  //statically typed as string
str = 5;               //would throw an error since java is statically typed

Mentre in una lingua tipizzata in modo dinamico il tipo è dinamico , il che significa che dopo aver impostato una variabile su un tipo, è possibile modificarlo. Questo perché la digitazione è associata al valore anziché alla variabile.

Ad esempio in Python:

str = "Hello" # it is a string
str = 5       # now it is an integer; perfectly OK

D'altra parte, la digitazione forte / debole in una lingua è correlata a conversioni di tipo implicite (in parte prese dalla risposta di @ Dario):

Ad esempio in Python:

str = 5 + "hello" 
# would throw an error since it does not want to cast one type to the other implicitly. 

mentre in PHP:

$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0 
// PHP is weakly typed, thus is a very forgiving language.

La digitazione statica consente di verificare la correttezza del tipo al momento della compilazione. Le lingue tipizzate staticamente vengono generalmente compilate e vengono interpretate le lingue tipizzate dinamicamente. Pertanto, le lingue digitate in modo dinamico possono controllare la digitazione in fase di esecuzione.


2
ottima risposta e complimenti per l'utilizzo di esempi concreti.
Giuliano A.

3
Ecco perché PHP deve essere usato con grande cura.
Ali Gajani,

1
Gli esempi di lingua sono davvero utili. Molto apprezzato.
J Mullen,

In questo senso, Java verrebbe mai leggermente tipizzato in modo così debole perché è possibile concatenare le non stringhe con le stringhe e a causa del disinserimento automatico / boxe?
Stephen Paul,

1
@StephenPaul hai ragione, la mia risposta può essere compresa in questo modo e non è così. Ho usato la concatenazione per motivi di semplicità, ma in effetti la forza / debolezza riguarda la conversione implicita del tipo della variabile stessa.
Mehmet

20

Digitazione debole significa che il tipo di un oggetto può cambiare a seconda del contesto. Ad esempio, in una lingua debolmente tipizzata, la stringa "123" può essere considerata come il numero 123 se si aggiunge un altro numero. Esempi di lingue con digitazione debole sono bash, awk e PHP.

Un altro tipo di linguaggio debolmente tipizzato è C, in cui i dati di un indirizzo di memoria possono essere trattati come un tipo diverso mediante il cast.

In un linguaggio fortemente tipizzato il tipo di un oggetto non cambia: un int è sempre un int e il tentativo di usarlo come stringa comporterà un errore. Sia Java che Python sono fortemente tipizzati.

La differenza tra la tipizzazione dinamica e statica è quando vengono applicate le regole del tipo. In una lingua tipizzata staticamente, il tipo di ogni variabile e parametro deve essere dichiarato nella sorgente e viene applicato al momento della compilazione. In una lingua tipizzata in modo dinamico, i tipi vengono controllati solo quando vengono utilizzati in fase di esecuzione. Quindi Java è tipizzato staticamente e Python è digitato dinamicamente.

Tuttavia a volte i confini possono essere un po 'sfocati. Ad esempio, sebbene Java sia tipizzato staticamente, ogni volta che si utilizza reflection o un cast (ad esempio quando si utilizzano contenitori di oggetti), si sta rinviando il controllo del tipo al runtime.

Allo stesso modo, le lingue più tipizzate verranno comunque convertite automaticamente tra numeri interi e float (e in alcune lingue BigInts di precisione abitraria).


1
Non posso essere d'accordo con questa frase -. "In una lingua tipizzata staticamente, il tipo di ogni variabile e parametro deve essere dichiarato nella sorgente" - in SML i tipi di variabili non devono essere dichiarati (ogni volta che vengono controllati). Diciamo che la funzione fprende argomento x( fun f(x)) [** quindi nessun tipo viene dichiarato **] e il corpo della funzione lo è x+1. Senza nessun tipo dichiarato, il compilatore scoprirà che xdeve essere un int. - fun f x = x + 1; val f = fn : int -> int
Filip Bartuzi,

Per quanto riguarda C, il casting non è contrario alla tipizzazione forte, ma C consente di aggiungere diversi tipi anche senza casting, ad esempio:5 + 'c' // OK
mehmet

3
@mehmet: in C, i valori dei caratteri sono nel dominio intero, quindi quel particolare esempio non viola la sicurezza del tipo. 'c' è solo zucchero sintattico per 99. C non ha un tipo di carattere dedicato.
Peter Lewerin,

Peter Lewerin: giusto avrei dovuto dare un esempio migliore. Sfortunatamente, sono passati quasi 20 anni da quando non ho toccato C :)
mehmet il

1
C non un linguaggio debolmente tipizzato . È solo che Java, C # ecc. Sono linguaggi tipizzati più fortemente rispetto a C. Leggi di più qui - en.wikipedia.org/wiki/Strong_and_weak_typing Se controlli la definizione di linguaggio "debolmente" digitato allora linguaggi "debolmente" sono quelli in cui puoi fare qualsiasi tipo di conversione, ad esempio un int può essere "implicitamente" convertito o lanciato in una stringa, ora pensi a te stesso se questo è possibile in C o no?
hagrawal,

15

Oggi, facendo ricerche su questo argomento, mi sono imbattuto in questo fantastico articolo http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html Ha chiarito molte cose cose per me e ho pensato che potrebbe aggiungere ad alcune delle grandi risposte di cui sopra.

Digitazione forte e debole:

Probabilmente il modo più comune in cui vengono classificati i sistemi di tipo è "forte" o "debole". Questo è un peccato, dal momento che queste parole non hanno quasi alcun significato. È possibile, in misura limitata, confrontare due lingue con sistemi di tipo molto simili e designarne una che abbia il più forte di quei due sistemi. Oltre a ciò, le parole non significano nulla.

Tipi statici e dinamici

Questa è quasi l'unica classificazione comune dei sistemi di tipo che ha un significato reale. È un dato di fatto, il suo significato è spesso sottovalutato [...] I sistemi di tipo dinamico e statico sono due cose completamente diverse, i cui obiettivi sembrano sovrapporsi parzialmente.

Un sistema di tipo statico è un meccanismo mediante il quale un compilatore esamina il codice sorgente e assegna etichette (chiamate "tipi") a parti della sintassi, e quindi le utilizza per dedurre qualcosa sul comportamento del programma. Un sistema di tipo dinamico è un meccanismo mediante il quale un compilatore genera codice per tenere traccia del tipo di dati (per coincidenza, chiamato anche "tipo") utilizzato dal programma. L'uso della stessa parola "tipo" in ciascuno di questi due sistemi non è, ovviamente, del tutto casuale; tuttavia si comprende che abbia una sorta di debole significato storico. Una grande confusione deriva dal tentativo di trovare una visione del mondo in cui "tipo" significhi davvero la stessa cosa in entrambi i sistemi. Non

Tipi espliciti / impliciti:

Quando vengono usati questi termini, si riferiscono alla misura in cui un compilatore ragionerà sui tipi statici di parti di un programma. Tutti i linguaggi di programmazione hanno una qualche forma di ragionamento sui tipi. Alcuni ne hanno più di altri. ML e Haskell hanno tipi impliciti, in quanto non sono necessarie dichiarazioni di tipo (o pochissime, a seconda della lingua e delle estensioni in uso). Java e Ada hanno tipi molto espliciti e uno dichiara costantemente i tipi di cose. Tutto quanto sopra ha (relativamente, rispetto a C e C ++, per esempio) sistemi di tipo statico forte.


8

Da Scott's Programming Language Pragmatics , terza edizione pagina 291, abbiamo

Il controllo del tipo è il processo per garantire che un programma obbedisca alle regole di compatibilità del tipo della lingua. Una violazione delle regole è nota come scontro di tipo. Si dice che una lingua sia fortemente tipizzata se proibisce, in modo che l'implementazione della lingua possa far rispettare, l'applicazione di qualsiasi operazione a qualsiasi oggetto che non sia destinato a supportare tale operazione. Si dice che una lingua sia tipizzata staticamente se è fortemente tipizzata e il controllo del tipo può essere eseguito al momento della compilazione. Nel senso più stretto del termine, poche lingue sono tipizzate staticamente. In pratica, il termine è spesso applicato alle lingue in cui la maggior parte dei controlli dei tipi può essere eseguita in fase di compilazione e il resto può essere eseguito in fase di esecuzione.

Alcuni esempi: Ada è fortemente tipizzato e per la maggior parte tipicamente statico (determinati vincoli di tipo devono essere controllati in fase di esecuzione). Un'implementazione Pascal può anche eseguire la maggior parte del controllo del tipo al momento della compilazione, sebbene il linguaggio non sia tipizzato in modo abbastanza forte: i record di varianti senza tag (da discutere nella Sezione 7.3.4) sono la sua unica scappatoia. C89 è significativamente più fortemente tipizzato rispetto ai suoi dialetti precedenti, ma ancora significativamente meno fortemente tipizzato di Pascal. Le sue lacune includono i sindacati, le subroutine con un numero variabile di parametri e l'interoperabilità di puntatori e matrici (da discutere nella Sezione 7.7.1). Le implementazioni di C raramente controllano qualsiasi cosa in fase di esecuzione.

Il controllo del tipo dinamico (runtime) è una forma di associazione tardiva e tende a essere trovato in lingue che ritardano anche altri problemi fino al runtime. Lisp e Smalltalk sono tipizzati in modo dinamico (sebbene fortemente). La maggior parte dei linguaggi di scripting è anche tipizzata in modo dinamico; alcuni (ad esempio, Python e Ruby) sono fortemente tipizzati. Le lingue con scoping dinamico sono generalmente tipizzate in modo dinamico (o non digitate affatto): se il compilatore non è in grado di identificare l'oggetto a cui si riferisce un nome, di solito non è nemmeno in grado di determinare il tipo di oggetto.

Quindi, in termini semplici, la tipizzazione statica / dinamica si riferisce al momento in cui si verifica il controllo del tipo: tempo di compilazione per la tipizzazione statica e tempo di esecuzione per linguaggi dinamici. Allo stesso modo, la tipizzazione forte / debole si riferisce all'aggressività di una lingua nel far rispettare il suo sistema di tipi.

Ho provato a tradurre la descrizione di Scott in un bel diagramma, che ho pubblicato di seguito.

Il piano di battitura statico / dinamico - forte / debole


5

Penso che gli altri colleghi abbiano fatto un buon lavoro esp. spiegando la differenza tra tipizzazione statica e dinamica. Ma per quanto riguarda la tipizzazione forte e debole, si dovrebbe dire che ci sono diverse comprensioni / opinioni.

Ecco due esempi:

  • Alcuni dicono che Haskell è fortemente tipizzato, perché non è permesso di fare eventuali conversioni di tipo.

  • Altri (ad esempio il punto di vista di Dario) affermano che un linguaggio che consente di convertire implicitamente da stringa a numero di proposito è tipizzato in modo debole, ma anche altri lo chiamano semplicemente "duck ducking".

Entrambe le affermazioni evidenziano non gli estremi opposti di un sistema di tipi, ma aspetti completamente diversi. Quindi mi unisco al punto di vista del signor Ramsey di non usare i termini "forte" e "debole" per distinguere tra sistemi di tipo.


5

Lingue tipicamente dinamiche v / s

  • Le lingue tipizzate staticamente sono quelle in cui viene eseguita la verifica del tipo al momento della compilazione, quindi ciò significa anche che nelle lingue tipizzate staticamente ogni variabile ha un tipo e non cambia nel corso. Ora, al contrario, i linguaggi tipizzati dinamicamente sono quelli in cui viene eseguito il controllo del tipo in fase di esecuzione e non esiste un controllo del tipo in fase di compilazione, quindi ciò significa anche che nei linguaggi tipizzati dinamicamente potrebbe esserci o meno un tipo associato a una variabile e se un tipo è associato, potrebbe essere un tipo generico come "var" in JS che vale sia per una stringa che per un numero.
    • “Le implementazioni di linguaggi controllati dinamicamente dal tipo generalmente associano ciascun oggetto di runtime a un tag di tipo (ovvero un riferimento a un tipo) contenente le informazioni sul tipo. Queste informazioni sul tipo di runtime (RTTI) possono anche essere utilizzate per implementare funzionalità di invio dinamico, associazione tardiva, down casting, riflessione e simili. "
  • Anche se il linguaggio è tipizzato staticamente, potrebbe comunque avere alcune funzionalità tipizzate dinamicamente, il che significa sostanzialmente che anche una sorta di controllo del tipo in fase di esecuzione. Questo è utile nel casting di tipi.
    • "Un certo numero di utili e comuni funzioni del linguaggio di programmazione non possono essere verificate staticamente, come il down casting. Pertanto, molte lingue avranno il controllo sia statico che dinamico; il controllo statico del tipo verifica ciò che può e i controlli dinamici verificano il resto. "
  • "Alcune lingue consentono la scrittura di codice non sicuro per i tipi. Ad esempio, in C, i programmatori possono lanciare liberamente un valore tra due tipi qualsiasi che hanno le stesse dimensioni. "
  • Il vantaggio di linguaggi tipizzati "staticamente" è che:
    • Poiché la maggior parte del controllo del tipo viene eseguito in fase di compilazione, l'interprete o il runtime possono essere eseguiti alla massima velocità, senza preoccuparsi dei tipi.
    • Porta a un numero minore di eccezioni di runtime o errori relativi al tipo, poiché la maggior parte del controllo del tipo viene eseguito al momento della compilazione.
  • Il vantaggio di linguaggi tipizzati "dinamicamente" è che:
    • Potrebbero aiutare nella prototipazione estremamente veloce, poiché gli sviluppatori non devono capire il sistema dei tipi in modo che lo sviluppatore possa liberamente creare variabili ed eseguirlo, e questo porta alla prototipazione molto veloce.
  • Elenco delle lingue tipizzate staticamente e dinamicamente :
    • Staticamente:
      • Giava
      • C (C è un linguaggio tipicamente statico ma meno "fortemente" tipizzato rispetto a Java perché consente conversioni più implicite)
      • C ++
      • C #
    • dinamicamente:
      • PERL
      • PHP
      • Pitone
      • JavaScript
      • Rubino
  • Il controllo del tipo è un'importante funzione di sicurezza. Supponiamo che non vi sia alcun controllo del tipo e che un metodo accetti un oggetto di tipo "BankAccount" che ha un metodo chiamato "creditAccount (BankAccountDetails)", ora in fase di esecuzione se non esiste un controllo del tipo, posso passare un oggetto tutto mio classe che ha lo stesso metodo "creditAccount (BankAccountDetails)" e verrà eseguita, considerando che stiamo parlando di un linguaggio orientato agli oggetti perché OOP supporta il "polimorfismo" e qui ciò di cui stiamo discutendo non è altro che "polimorfismo". Quindi, fondamentalmente un linguaggio orientato agli oggetti (il che significa sostanzialmente che supporta il "polimorfismo") che non ha un forte controllo del tipo può portare a problemi di sicurezza.

Lingue fortemente tipizzate v / s

  • I linguaggi fortemente tipizzati sono quelli in cui le conversioni implicite non sono consentite in caso di perdita di precisione. Ad esempio, in Java, puoi lanciare un "int su long" perché non c'è perdita di precisione ma non puoi "implicitamente" trasmettere un "long to int" perché ci sarebbe una perdita di precisione. Al contrario, nei linguaggi debolmente tipizzati, sono consentite conversioni implicite anche se si verifica una perdita di precisione.
  • Penso che il linguaggio tipizzato in modo dinamico possa anche essere un linguaggio fortemente tipizzato se "in fase di esecuzione" non consente conversioni implicite in cui si verifica una perdita di precisione.

Buone ulteriori letture


hai citato "ora in fase di esecuzione se non esiste un controllo del tipo, quindi posso passare un oggetto della mia classe che ha lo stesso metodo" creditAccount (BankAccountDetails) "- se hai già superato il meccanismo che potrebbe impedirti di passare un oggetto allora come il controllo del tipo ti impedirà di chiamare quel metodo in caso di una lingua tipizzata staticamente?
Aseem Yadav,

@AseemYadav Cosa intendi con "* se hai già superato il meccanismo che potrebbe impedirti di passare un oggetto *"?
hagrawal,

come hai detto, è un'importante funzionalità di sicurezza e anche che potresti passare un oggetto della tua stessa classe con lo stesso metodo, quindi mi sembra che sembri essere una vulnerabilità solo quando stai provando a violare il codice di qualcun altro e se stai parlando nel contesto del codice che ti appartiene rispetto al suo più di un problema di prestazioni rispetto a quello relativo alla sicurezza, non è vero?
Aseem Yadav,

Non vi è alcun aspetto prestazionale, devi vederlo dal contesto del polimorfismo, quindi sarai in grado di comprenderne l'aspetto di sicurezza, ne ho parlato nello stesso paragrafo.
hagrawal,

1

I linguaggi tipizzati staticamente richiedono generalmente di dichiarare i tipi di variabili, che viene quindi verificato in fase di compilazione per ridurre gli errori. La parola "statico" in "tipicamente" si riferisce a "analisi del codice statico", che è il processo di esame del codice prima di eseguirlo. Sebbene sia possibile che un linguaggio tipicamente statico deduca il tipo della variabile dal lato destro di un'espressione o dei parametri effettivi, in pratica la maggior parte dei linguaggi tipicamente statici richiede che i tipi variabili siano dichiarati esplicitamente.

I linguaggi tipizzati dinamicamente generalmente non richiedono che le dichiarazioni di variabili abbiano tipi e ne deducono tipi variabili in base al tipo calcolato come risultato della valutazione del lato destro di ogni istruzione di assegnazione o dei parametri effettivi a una chiamata di funzione. Poiché alla variabile possono essere assegnate più assegnazioni nel corso della sua durata, il suo tipo può cambiare nel tempo ed è per questo che viene chiamato "tipizzato dinamicamente". Inoltre, l'ambiente di runtime deve tenere traccia del tipo corrente per ogni variabile, quindi il tipo è associato al valore anziché alla dichiarazione della variabile. Questo può essere considerato un sistema di informazioni sul tipo di runtime (RTTI).

È possibile combinare elementi di linguaggi tipizzati staticamente e dinamicamente. Ad esempio, C # supporta variabili tipizzate sia staticamente che dinamicamente, mentre i linguaggi orientati agli oggetti generalmente supportano il down-casting della gerarchia dei tipi. I linguaggi tipizzati staticamente di solito offrono vari modi per aggirare il controllo del tipo, ad esempio usando il cast, la riflessione e l'invocazione dinamica.

Digitazione forte vs. debole indica un continuum di quanto la lingua cerca di prevenire i bug a causa dell'uso di una variabile come se fosse un tipo quando in realtà è un altro tipo. Ad esempio, sia C che Java sono linguaggi tipizzati staticamente, tuttavia Java utilizza un controllo del tipo molto più efficace rispetto a C. Il seguente codice C è felice di compilare ed eseguire e inserirà un valore casuale nella variabile b in fase di runtime, molto probabilmente causando un bug:

char *a = "123";
int b = (int)a;

Il codice Java equivalente produrrà un errore di compilazione, che è generalmente preferibile:

String a = "123"
int b = (int)a;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.