web-dev-qa-db-fra.com

Quelle est la différence entre les langages à typage statique et dynamique?

J'entends beaucoup dire que les nouveaux langages de programmation sont typés de manière dynamique, mais qu'est-ce que cela signifie réellement quand on dit qu'un langage est typé de manière dynamique par rapport à un typage statique?

769
Rachel

Langues typées statiquement

Un langage est typé statiquement si le type d'une variable est connu au moment de la compilation. Pour certaines langues, cela signifie que vous en tant que programmeur devez spécifier le type de chaque variable (par exemple: Java, C, C++); d'autres langages offrent une certaine forme d'inférence type, la capacité du système de types à déduire le type d'une variable (par exemple: OCaml, Haskell, Scala, Kotlin)

Le principal avantage ici est que le compilateur peut effectuer toutes sortes de vérifications, ce qui permet de détecter beaucoup de bogues triviaux très tôt.

Exemples: C, C++, Java, Rust, Go, Scala

Langages typés dynamiquement

Un langage est typé dynamiquement si le type est associé à des valeurs d'exécution et non à des variables/champs nommés/etc. Cela signifie qu'en tant que programmeur, vous pouvez écrire un peu plus vite car vous n'avez pas à spécifier les types à chaque fois (sauf si vous utilisez un langage de type statique avec type inference). 

Exemples: Perl, Ruby, Python, PHP, JavaScript

La plupart des langages de script ont cette fonctionnalité car il n’existe aucun compilateur pour effectuer une vérification de type statique, mais vous pouvez vous retrouver à rechercher un bogue dû à l’interprétation erronée du type d’une variable par l’interprète. Heureusement, les scripts ont tendance à être petits, les bugs n'ont donc pas tant d'endroits où se cacher.

La plupart des langages à typage dynamique vous permettent de fournir des informations de type, mais n'en ont pas besoin. Un langage en cours de développement, Rascal , adopte une approche hybride permettant un typage dynamique au sein de fonctions mais imposant un typage statique pour la signature de fonction.

694
NomeN

Les langages de programmation statiquement typés vérifient le type (c'est-à-dire le processus de vérification et d'application des contraintes de types) à compile-time par opposition à run-time .

Les langages de programmation à typage dynamique font la vérification de type à à l'exécution par opposition à à la compilation .

299

Voici un exemple montrant comment Python (typé dynamiquement) et Go (typé statiquement) traitent une erreur de type: 

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

Python tape la vérification au moment de l'exécution, et par conséquent:

silly(2)

Fonctionne parfaitement bien et produit le résultat attendu Hi. L'erreur est déclenchée uniquement si la ligne problématique est touchée:

silly(-1)

Produit

TypeError: unsupported operand type(s) for +: 'int' and 'str'

parce que la ligne pertinente a été réellement exécutée.

Allez par contre fait la vérification de type à la compilation:

package main

import ("fmt"
)

func silly(a int) {
    if (a > 0) {
        fmt.Println("Hi")
    } else {
        fmt.Println("3" + 5)
    }
}

func main() {
    silly(2)
}

Ce qui précède ne sera pas compilé, avec l'erreur suivante:

invalid operation: "3" + 5 (mismatched types string and int)
259
Akavall

En termes simples, dans un langage langage typé statiquement, les types de variables sont static, ce qui signifie que lorsque vous définissez une variable sur un type, vous ne pouvez pas le modifier. En effet, la frappe est associée à la variable plutôt qu'à la valeur à laquelle elle fait référence. 

Par exemple en Java: 

String str = "Hello";  //variable str statically typed as string
str = 5;               //would throw an error since str is supposed to be a string only

Où d'autre part: dans un langage dynamiquement typé, les types de variables sont dynamic, ce qui signifie qu'après avoir défini une variable sur un type, vous POUVEZ le modifier. En effet, le typage est associé à la valeur qu'il prend plutôt qu'à la variable elle-même. 

Par exemple en Python:

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

Il est donc préférable de considérer les variables dans les langages à typage dynamique comme seulement des pointeurs génériques vers des valeurs typées. 

En résumé, type décrit (ou aurait dû décrire) les variables du langage plutôt que le langage lui-même. Il aurait pu être mieux utilisé comme un langage avec des variables de type statique versus un langage avec des variables de type dynamique IMHO.

Les langages à typage statique sont généralement des langages compilés. Par conséquent, les compilateurs vérifient les types (ce qui est parfaitement logique, car les types ne peuvent pas être modifiés ultérieurement au moment de l'exécution).

Les langages à typage dynamique étant généralement interprétés, la vérification de type (le cas échéant) est effectuée au moment de leur utilisation. Cela entraîne bien sûr des coûts de performance et est l’une des raisons pour lesquelles les langages dynamiques (python, Ruby, php, par exemple) ne sont pas aussi performants que ceux typés (Java, c #, etc.). D'un autre point de vue, les langages à typage statique ont un coût de démarrage plus élevé: vous obligent généralement à écrire plus de code, plus difficile. Mais cela paye plus tard. 

La bonne chose est que les deux côtés empruntent des fonctionnalités de l'autre côté. Les langages typés incorporent des fonctionnalités plus dynamiques, par exemple les génériques et les bibliothèques dynamiques en c #, et les langages dynamiques incluent davantage de vérification de type, par exemple les annotations de types en python ou la variante HACK de PHP, qui ne sont généralement pas au cœur du langage et ne sont pas utilisables sur. demande. 

En ce qui concerne le choix de la technologie, aucune des deux parties n’a de supériorité intrinsèque sur l’autre. Que vous souhaitiez plus de contrôle ou plus de flexibilité est une question de préférence. il suffit de choisir le bon outil pour le travail et de vérifier ce qui est disponible en termes opposés avant d'envisager un changement. 

133
mehmet

http://en.wikipedia.org/wiki/Type_system

Saisie statique

Un langage de programmation utilise un typage statique lorsque la vérification du type est effectuée pendant la compilation, par opposition à l'exécution. En typage statique, les types sont associés à des variables et non à des valeurs. Les langages à typage statique incluent Ada, C, C++, C #, JADE, Java, Fortran, Haskell, ML, Pascal, Perl (en ce qui concerne la distinction des scalaires, des tableaux, des hachages et des sous-programmes) et Scala. Le typage statique est une forme limitée de vérification de programme (voir sécurité de type): il permet donc de détecter de nombreuses erreurs de type au début du cycle de développement. Les vérificateurs de type statiques n'évaluent que les informations de type pouvant être déterminées au moment de la compilation, mais sont en mesure de vérifier que les conditions vérifiées sont valables pour toutes les exécutions possibles du programme, ce qui évite de devoir répéter les vérifications de type à chaque exécution du programme. L’exécution du programme peut également être rendue plus efficace (c’est-à-dire plus rapide ou en prenant moins de mémoire) en omettant les contrôles de type à l’exécution et en permettant d’autres optimisations.

Comme ils évaluent les informations de type lors de la compilation et manquent par conséquent d'informations de type uniquement disponibles au moment de l'exécution, les vérificateurs de type statiques sont conservateurs. Ils rejetteront certains programmes qui se comporteront peut-être bien au moment de l'exécution, mais il est impossible de déterminer statiquement qu'ils sont bien typés. Par exemple, même si une expression a toujours la valeur true au moment de l’exécution, un programme contenant le code

if <complex test> then 42 else <type error>

sera rejeté comme mal typé, car une analyse statique ne peut pas déterminer que la branche else ne sera pas prise. [1] Le comportement conservateur des vérificateurs de type statiques est avantageux lorsqu'il est rarement faux. Un vérificateur de type statique peut détecter les erreurs de type dans les chemins de code rarement utilisés. Sans vérification de type statique, même les tests de couverture de code avec une couverture de code à 100% risquent de ne pas trouver ces erreurs de type. Les tests de couverture de code peuvent ne pas détecter ces erreurs de type car la combinaison de tous les endroits où des valeurs sont créées et de tous les endroits où une certaine valeur est utilisée doit être prise en compte.

Les langages statiquement typés les plus utilisés ne sont pas formellement sûrs. Ils ont des "lacunes" dans la spécification du langage de programmation permettant aux programmeurs d'écrire du code qui contourne la vérification effectuée par un vérificateur de type statique et aborde ainsi une gamme plus large de problèmes. Par exemple, Java et la plupart des langages de style C ont une frappe punitive, et Haskell possède des fonctionnalités telles que unsafePerformIO: de telles opérations peuvent être dangereuses au moment de l'exécution, car elles peuvent entraîner un comportement indésirable en raison d'une saisie incorrecte des valeurs lors de le programme fonctionne.

Saisie dynamique

Un langage de programmation est dit dynamiquement typé, ou simplement "dynamique", lorsque la majorité de sa vérification de type est effectuée à l'exécution et non à la compilation. En typage dynamique, les types sont associés à des valeurs et non à des variables. Les langages à typage dynamique incluent Groovy, JavaScript, LISP, Lua, Objective-C, Perl (en ce qui concerne les types définis par l'utilisateur mais pas les types intégrés), PHP, Prolog, Python, Ruby, Smalltalk et Tcl. Par rapport au typage statique, le typage dynamique peut être plus flexible (par exemple, en permettant aux programmes de générer des types et des fonctionnalités basés sur des données d'exécution), mais aux dépens de moins de garanties a priori. En effet, un langage à typage dynamique accepte et tente d’exécuter certains programmes qui peuvent être déclarés invalides par un vérificateur de type statique.

Le typage dynamique peut entraîner des erreurs de type à l'exécution, c'est-à-dire qu'au moment de l'exécution, une valeur peut avoir un type inattendu et qu'une opération non logique pour ce type est appliquée. Cette opération peut se produire longtemps après l'endroit où l'erreur de programmation a été commise, c'est-à-dire l'endroit où le type de données erroné est passé dans un endroit qu'il n'aurait pas dû avoir. Cela rend le bug difficile à localiser.

Les systèmes de langage à typage dynamique, comparés à leurs cousins ​​à typage statique, effectuent moins de vérifications de "compilation" sur le code source (mais vérifient, par exemple, que le programme est syntaxiquement correct). Les contrôles d'exécution peuvent être potentiellement plus sophistiqués, car ils peuvent utiliser des informations dynamiques ainsi que toute information présente lors de la compilation. D'autre part, les contrôles d'exécution n'affirment que le maintien des conditions dans une exécution particulière du programme, et ces contrôles sont répétés pour chaque exécution du programme.

Le développement dans des langages à typage dynamique est souvent pris en charge par des pratiques de programmation telles que les tests unitaires. Le test est une pratique clé dans le développement de logiciels professionnels et est particulièrement important dans les langages à typage dynamique. En pratique, les tests effectués pour garantir le fonctionnement correct du programme peuvent détecter une gamme d'erreurs beaucoup plus large que la vérification de type statique, mais ne peuvent pas au contraire rechercher de manière aussi complète les erreurs que les tests et la vérification de type statique sont capables de détecter. Les tests peuvent être intégrés au cycle de construction du logiciel, auquel cas il peut être considéré comme une vérification "à la compilation", en ce sens que l'utilisateur du programme n'aura pas à exécuter manuellement de tels tests.

Références

  1. Pierce, Benjamin (2002). Types et langages de programmation. MIT Appuyez sur. ISBN 0-262-16209-1.
37
Jacob

La terminologie "typée dynamiquement" est malheureusement trompeuse. Toutes les langues sont typées statiquement et les types sont des propriétés d'expressions (et non de valeurs comme le pensent certains). Cependant, certaines langues ont un seul type. Celles-ci sont appelées langages uni-typés. Un exemple d'un tel langage est le calcul lambda non typé.

Dans le calcul lambda non typé, tous les termes sont des termes lambda, et la seule opération pouvant être effectuée sur un terme consiste à l'appliquer à un autre terme. Par conséquent, toutes les opérations entraînent toujours une récursion infinie ou un terme lambda, mais ne signalent jamais d'erreur.

Cependant, si nous augmentions le calcul lambda non typé avec des nombres primitifs et des opérations arithmétiques, nous pourrions alors effectuer des opérations absurdes, telles que l’ajout de deux termes lambda: (λx.x) + (λy.y). On pourrait soutenir que la seule chose sensée à faire est de signaler une erreur lorsque cela se produit, mais pour ce faire, chaque valeur doit être étiquetée avec un indicateur indiquant si le terme est un terme lambda ou un nombre. L'opérateur d'addition vérifiera ensuite qu'en réalité les deux arguments sont étiquetés en tant que nombres et s'ils ne le sont pas, signalent une erreur. Notez que ces balises sont des types not, car les types sont des propriétés de programmes et non des valeurs produites par ces programmes.

Un langage uni-typé qui fait cela s'appelle dynamiquement typé.

Les langages tels que JavaScript, Python et Ruby sont tous uni-typés. De nouveau, l'opérateur typeof en JavaScript et la fonction type en Python ont des noms trompeurs; ils renvoient les balises associées aux opérandes, pas leurs types. De même, dynamic_cast en C++ et instanceof en Java font pas font des vérifications de type.

14
rightfold

Compilé vs interprété

"Quand le code source est traduit"

  • Code source : Code original (généralement saisi par un humain dans un ordinateur)
  • Traduction : Conversion du code source en quelque chose qu'un ordinateur peut lire (code machine)
  • Durée d'exécution : Période pendant laquelle le programme exécute des commandes (après la compilation, si compilé)
  • Langage compilé : Code traduit avant l'exécution
  • Langue interprétée : Code traduit à la volée, en cours d'exécution

Dactylographie

"Quand les types sont cochés"

5 + '3' est un exemple d'erreur de type dans les langages fortement typés tels que Go et Python, car ils ne permettent pas de "coercition de type" -> la possibilité pour une valeur de changer de type dans certains contextes, tels que la fusion de deux les types. Les langages faiblement typés, tels que JavaScript, ne génèrent pas d'erreur de frappe (le résultat est '53').

  • Static : Types vérifiés avant l'exécution
  • Dynamique : Types vérifiés à la volée, en cours d'exécution

Les définitions de "Static & Compiled" et "Dynamic & Interpreted" sont assez similaires ... mais rappelez-vous que c'est "quand les types sont vérifiés" ou "quand le code source est traduit". 

Vous obtiendrez les mêmes erreurs de type, que le langage soit compilé ou interprété ! Vous devez séparer ces termes conceptuellement.


Exemple Python

Dynamique, interprété

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

silly(2)

Parce que Python est à la fois interprété et dynamiquement typé, il ne fait que traduire et vérifier le code sur lequel il est exécuté. Le bloc else ne s'exécute jamais, donc 5 + '3' n'est même jamais regardé!

Et si c'était typé statiquement?

Une erreur de type serait renvoyée avant même que le code soit exécuté. Il effectue toujours la vérification de type avant l'exécution même s'il est interprété.

Et si c'était compilé? 

Le bloc else serait traduit/examiné avant l'exécution, mais comme il est typé dynamiquement, il ne générerait pas d'erreur! Les langages typés dynamiquement ne vérifient pas les types avant leur exécution, et cette ligne ne s'exécute jamais.


Go exemple

Statique, compilé

package main

import ("fmt"
)

func silly(a int) {
  if (a > 0) {
      fmt.Println("Hi")
  } else {
      fmt.Println("3" + 5)
  }
}

func main() {
  silly(2)
}

Les types sont vérifiés avant l'exécution (statique) et l'erreur de type est immédiatement détectée! Les types seraient toujours vérifiés avant l'exécution si elle était interprétée, ce qui donnerait le même résultat. S'il était dynamique, cela ne générerait aucune erreur même si le code serait examiné lors de la compilation.


Performance

Un langage compilé aura de meilleures performances au moment de l'exécution s'il est typé statiquement (par opposition à dynamique); la connaissance des types permet l'optimisation du code machine.

Les langages à typage statique ont intrinsèquement de meilleures performances au moment de l’exécution car ils n’ont pas besoin de vérifier les types de manière dynamique lors de l’exécution (il vérifie avant de les exécuter).

De même, les langages compilés sont plus rapides au moment de l'exécution, car le code a déjà été traduit au lieu de devoir "interpréter"/traduire à la volée.

Notez que les langages compilés et typés statiquement auront un délai avant de s'exécuter pour la traduction et la vérification de type, respectivement.


Plus de différences

Le typage statique détecte les erreurs tôt, au lieu de les trouver pendant l'exécution (particulièrement utile pour les programmes longs). Il est plus "strict" en ce sens qu'il ne permet aucune erreur de type dans votre programme et empêche souvent les variables de changer de type, ce qui protège davantage contre les erreurs involontaires.

num = 2
num = '3' // ERROR

La frappe dynamique est plus flexible, ce que certains apprécient. Cela permet généralement aux variables de changer de type, ce qui peut entraîner des erreurs inattendues.

5
JBallin

La vérification de type des langages statiquement typés lors de la compilation et le type ne peuvent PAS changer. (Ne soyez pas mignon avec les commentaires de typographie, une nouvelle variable/référence est créée).

La vérification de type des langues à typage dynamique au moment de l'exécution et le type d'une variable PEUVENT être modifiés au moment de l'exécution.

5
RESTfulGeoffrey

Des définitions simples et douces, mais qui répondent aux besoins suivants: Les langages à typage statique lient le type à une variable pour toute son étendue (Seg: SCALA) Les langages à typage dynamique lient le type à la valeur réelle référencée par une variable.

4
user3627021

Langages typés statiquement : chaque variable et expression est déjà connue au moment de la compilation. 

(int a; a ne peut prendre que des valeurs de type entier au moment de l'exécution)

Exemples: C, C++, Java

Langages à typage dynamique : les variables peuvent recevoir différentes valeurs au moment de l'exécution et leur type est défini au moment de l'exécution. 

(var a; a peut prendre n'importe quel type de valeur au moment de l'exécution)

Exemples: Ruby, Python.

3
Raman Gupta
  • Dans un langage à typage statique, une variable est associée à un type connu lors de la compilation, et ce type reste inchangé tout au long de l'exécution d'un programme. De manière équivalente, on ne peut attribuer à la variable qu'une valeur qui est une instance du type connu/spécifié.
  • Dans un langage typé dynamiquement, une variable n'a pas de type et sa valeur pendant l'exécution peut être n'importe quelle forme ou forme.
3
Chudong

Les langages à typage statique comme C++, Java et les langages à typage dynamique comme Python ne diffèrent que par l’exécution du type de la variable . Les langues statiquement typées ont un type de données statique pour la variable, ici le type de données est vérifié lors de la compilation, le débogage est donc beaucoup plus simple ... alors que Les langues dynamiquement typées ne font pas la même chose, le type de données est vérifié quelle exécution du programme et donc le débogage est un peu difficile.

De plus, ils ont une très petite différence et peuvent être liés aux langues fortement typées et faiblement typées. Un langage fortement typé ne vous permet pas d'utiliser un type comme un autre, par exemple. C et C++ ... alors que les langages faiblement typés permettent eg.python

2
Akash sharma

Langage typé dynamiquement aide à prototyper rapidement les concepts d’algorithmes sans avoir à penser aux types de variables à utiliser (ce qui est une nécessité dans le libellé statique e). 

0
Pavan Kanajar

Langages typés statiques (le compilateur résout les appels de méthodes et compile les références):

  • généralement de meilleures performances
  • compilation plus rapide des erreurs
  • meilleur IDE support
  • ne convient pas pour travailler avec des formats de données non définis
  • plus difficile de démarrer un développement lorsque le modèle n’est pas défini lorsque
  • temps de compilation plus long
  • dans de nombreux cas nécessite d'écrire plus de code

Langages typés dynamiques (décisions prises dans le programme en cours):

  • performance inférieure
  • développement plus rapide
  • certains bogues pourraient être détectés seulement plus tard au moment de l'exécution
  • bon pour les formats de données non définis (méta-programmation)
0
MagGGG