J'entends beaucoup dire que les nouveaux langages de programmation sont typés dynamiquement, mais qu'est-ce que cela signifie réellement lorsque nous disons qu'un langage est typé dynamiquement vs statiquement?
J'entends beaucoup dire que les nouveaux langages de programmation sont typés dynamiquement, mais qu'est-ce que cela signifie réellement lorsque nous disons qu'un langage est typé dynamiquement vs statiquement?
Réponses:
Un langage est typé statiquement si le type d'une variable est connu au moment de la compilation. Pour certains langages, cela signifie qu'en tant que programmeur, vous devez spécifier le type de chaque variable (par exemple: Java, C, C ++); d'autres langages offrent une certaine forme d' inférence de type , la capacité du système de type à déduire le type d'une variable (par exemple: OCaml, Haskell, Scala, Kotlin)
Le principal avantage ici est que toutes sortes de vérifications peuvent être effectuées par le compilateur, et donc de nombreux bugs triviaux sont détectés à un stade très précoce.
Exemples: C, C ++, Java, Rust, Go, Scala
Une langue est typée dynamiquement si le type est associé à des valeurs d'exécution, et non nommé variables / champs / etc. Cela signifie que vous, en tant que programmeur, pouvez écrire un peu plus rapidement car vous n'avez pas besoin de spécifier les types à chaque fois (sauf si vous utilisez un langage de type statique avec inférence de type ).
Exemples: Perl, Ruby, Python, PHP, JavaScript
La plupart des langages de script ont cette fonctionnalité car il n'y a pas de compilateur pour faire la vérification de type statique de toute façon, mais vous pouvez vous retrouver à chercher un bogue qui est dû à l'interpréteur qui interprète mal le type d'une variable. Heureusement, les scripts ont tendance à être petits, donc les bogues n'ont pas tant d'endroits à cacher.
La plupart des langages typés dynamiquement vous permettent de fournir des informations de type, mais ne l'exigent pas. Un langage qui est en cours de développement, Rascal , adopte une approche hybride permettant le typage dynamique au sein des fonctions mais imposant un typage statique pour la signature de fonction.
Les langages de programmation à typage statique vérifient le type (c'est-à-dire le processus de vérification et d'application des contraintes des types) au moment de la compilation plutôt qu'au moment de l' exécution .
Les langages de programmation typés dynamiquement vérifient le type au moment de l' exécution plutôt qu'au moment de la compilation .
Exemples de langages typés statiquement: - Java, C, C ++
Exemples de langages typés dynamiquement: - Perl, Ruby, Python, PHP, JavaScript
Voici un exemple contrastant comment Python (typé dynamiquement) et Go (typé statiquement) gèrent une erreur de type:
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
Python vérifie le type au moment de l'exécution, et donc:
silly(2)
Fonctionne parfaitement bien et produit la sortie attendue Hi
. L'erreur n'est déclenchée que si la ligne problématique est atteinte:
silly(-1)
Produit
TypeError: unsupported operand type(s) for +: 'int' and 'str'
car la ligne correspondante a été exécutée.
Aller d'autre part fait la vérification de type au moment de 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 se compilera pas, avec l'erreur suivante:
invalid operation: "3" + 5 (mismatched types string and int)
runhaskell
, par exemple.
Autrement dit, dans un langage à typage statique, les types de variables sont statiques , ce qui signifie qu'une fois que vous avez défini une variable sur un type, vous ne pouvez pas la modifier. En effet, la saisie est associée à la variable plutôt qu'à la valeur à laquelle elle se réfère.
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 à typage dynamique, les types de variables sont dynamiques , ce qui signifie qu'après avoir défini une variable sur un type, vous POUVEZ le changer. En effet, la saisie est associée à la valeur qu'elle suppose 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 typés dynamiquement comme de simples pointeurs génériques vers des valeurs typées.
Pour résumer, tapez décrit (ou aurait dû décrire) les variables de la langue plutôt que la langue elle-même. Il aurait pu être mieux utilisé comme langue avec des variables typées statiquement contre une langue avec des variables typées dynamiquement IMHO.
Les langages typés statiquement sont généralement des langages compilés, ainsi, les compilateurs vérifient les types (c'est parfaitement logique, car les types ne peuvent pas être modifiés ultérieurement au moment de l'exécution).
Les langages typés dynamiquement sont généralement interprétés, ainsi la vérification de type (le cas échéant) se produit au moment de l'exécution lorsqu'ils sont utilisés. Bien sûr, cela entraîne un certain coût de performance et est l'une des raisons pour lesquelles les langages dynamiques (par exemple, python, ruby, php) ne sont pas aussi bons que ceux typés (java, c #, etc.). D'un autre point de vue, les langages typés statiquement ont plus de coût de démarrage: vous obligent généralement à écrire plus de code, un code plus dur. Mais cela rapporte plus tard.
La bonne chose est que les deux parties 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 plus de vérification de type, par exemple, les annotations de type en python ou la variante HACK de PHP, qui ne sont généralement pas au cœur du langage et utilisables sur demande.
En ce qui concerne le choix de la technologie, aucun côté n'a une supériorité intrinsèque sur l'autre. C'est juste une question de préférence si vous voulez plus de contrôle pour commencer ou de flexibilité. choisissez simplement le bon outil pour le travail et assurez-vous de vérifier ce qui est disponible en termes de l'opposé avant d'envisager un changement.
http://en.wikipedia.org/wiki/Type_system
Typage statique
On dit qu'un langage de programmation utilise un typage statique lorsque la vérification de type est effectuée pendant la compilation plutôt que pendant l'exécution. Dans le typage statique, les types sont associés à des variables et non à des valeurs. Les langages typés statiquement 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-routines) et Scala. Le typage statique est une forme limitée de vérification de programme (voir sécurité du type): en conséquence, il permet de détecter de nombreuses erreurs de type au début du cycle de développement. Les vérificateurs de type statiques évaluent uniquement les informations de type qui peuvent être déterminées au moment de la compilation, mais sont capables de vérifier que les conditions vérifiées sont valables pour toutes les exécutions possibles du programme, ce qui élimine la nécessité de 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 vérifications de type d'exécution et en permettant d'autres optimisations.
Étant donné qu'ils évaluent les informations de type lors de la compilation et manquent donc d'informations de type qui ne sont disponibles qu'au moment de l'exécution, les vérificateurs de type statiques sont conservateurs. Ils rejetteront certains programmes qui peuvent se comporter correctement au moment de l'exécution, mais qui ne peuvent pas être statiquement déterminés comme étant 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 statique est avantageux lorsqu'il est évalué à faux rarement: un vérificateur de type statique peut détecter des erreurs de type dans des 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% peuvent être incapables de trouver de telles erreurs de type. Les tests de couverture de code peuvent ne pas détecter de telles erreurs de type car la combinaison de tous les emplacements où des valeurs sont créées et de tous les emplacements où une certaine valeur est utilisée doit être prise en compte.
Les langues à typage statique les plus utilisées ne sont pas formellement sûres. Ils ont des "failles" 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 ainsi de résoudre un plus large éventail de problèmes. Par exemple, Java et la plupart des langages de style C ont une punition de type, et Haskell a des fonctionnalités telles que unsafePerformIO: ces opérations peuvent être dangereuses au moment de l'exécution, en ce qu'elles peuvent provoquer un comportement indésirable en raison d'une saisie incorrecte des valeurs lors de l'exécution du programme.
Saisie dynamique
Un langage de programmation est dit être typé dynamiquement, ou simplement «dynamique», lorsque la majorité de sa vérification de type est effectuée au moment de l'exécution plutôt qu'au moment de la compilation. En typage dynamique, les types sont associés à des valeurs et non à des variables. Les langages typés dynamiquement 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 au prix de moins de garanties a priori. Cela est dû au fait qu'un langage typé dynamiquement accepte et tente d'exécuter certains programmes qui peuvent être considérés comme invalides par un vérificateur de type statique.
La frappe dynamique peut entraîner des erreurs de type à l'exécution, c'est-à-dire qu'à l'exécution, une valeur peut avoir un type inattendu et 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 mauvais type de données est passé dans un endroit qu'il ne devrait pas 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 "au moment de la compilation" sur le code source (mais vérifieront, par exemple, que le programme est syntaxiquement correct). Les vérifications au moment de l'exécution peuvent potentiellement être plus sophistiquées, car elles peuvent utiliser des informations dynamiques ainsi que toute information présente lors de la compilation. D'un autre côté, les vérifications d'exécution affirment uniquement que les conditions sont respectées dans une exécution particulière du programme, et ces vérifications sont répétées pour chaque exécution du programme.
Le développement dans des langages typés dynamiquement est souvent soutenu par des pratiques de programmation telles que les tests unitaires. Les tests sont une pratique clé dans le développement de logiciels professionnels et sont particulièrement importants dans les langages typés dynamiquement. En pratique, les tests effectués pour garantir le bon fonctionnement du programme peuvent détecter une gamme d'erreurs beaucoup plus large que la vérification de type statique, mais à l'inverse, ils ne peuvent pas 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 incorporés dans le cycle de construction du logiciel, auquel cas ils peuvent être considérés comme une vérification "au moment de la compilation", dans la mesure où l'utilisateur du programme n'aura pas à exécuter manuellement de tels tests.
Références
- Pierce, Benjamin (2002). Types et langages de programmation. MIT Appuyez sur. ISBN 0-262-16209-1.
myObject[remoteDataName]
. Ensuite, il n'y a aucun moyen de savoir quelle propriété il choisira ou même s'il s'agit d'une propriété valide.
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 (pas de valeurs comme certains le pensent). Cependant, certaines langues n'ont qu'un seul type. Celles-ci sont appelées langues uni-typées. Un exemple d'une telle langue est le calcul lambda non typé.
Dans le calcul lambda non typé, tous les termes sont des termes lambda et la seule opération qui peut être effectuée sur un terme est de 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, nous avons été d'augmenter le calcul typées lambda avec des nombres primitifs et des opérations arithmétiques, nous pourrions effectuer des opérations insensées, comme l' ajout de deux termes lambda ensemble: (λ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 pouvoir le faire, chaque valeur doit être étiquetée avec un indicateur qui indique si le terme est un terme lambda ou un nombre. L'opérateur d'addition vérifiera alors qu'en effet les deux arguments sont étiquetés comme des nombres, et s'ils ne le sont pas, signalent une erreur. Notez que ces balises ne sont pas des types, 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 est appelé typé dynamiquement.
Les langages tels que JavaScript, Python et Ruby sont tous uni-typés. Encore une fois, l' typeof
opérateur en JavaScript et la type
fonction 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, ne faites pas de vérification de type.
"Lorsque le code source est traduit"
"Lorsque les types sont vérifié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 types. Les langages mal typés , tels que JavaScript, ne génèrent pas d'erreur de type (résulte en '53'
).
Les définitions de "Static & Compiled" et "Dynamic & Interpreted" sont assez similaires ... mais rappelez-vous que c'est "lorsque les types sont vérifiés" vs "lorsque le code source est traduit".
Vous obtiendrez les mêmes erreurs de type, que la langue soit compilée ou interprétée ! Vous devez séparer ces termes conceptuellement.
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 typé dynamiquement, il ne traduit et ne vérifie que le code sur lequel il s'exécute. Le else
bloc ne s'exécute jamais, il 5 + '3'
n'est donc même jamais regardé!
Et s'il était typé statiquement?
Une erreur de type serait levée avant même que le code soit exécuté. Il effectue toujours une vérification de type avant l'exécution même s'il est interprété.
Et si c'était compilé?
Le else
bloc serait traduit / examiné avant l'exécution, mais comme il est typé dynamiquement, il ne générera pas d'erreur! Les langages typés dynamiquement ne vérifient pas les types jusqu'à l'exécution, et cette ligne ne s'exécute jamais.
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 s'ils étaient interprétés, ayant le même résultat. S'il était dynamique, il ne générerait aucune erreur même si le code était examiné lors de la compilation.
Un langage compilé aura de meilleures performances au moment de l'exécution s'il est typé statiquement (vs dynamiquement); la connaissance des types permet d'optimiser le code machine.
Les langages de type statique ont intrinsèquement de meilleures performances au moment de l'exécution car ils n'ont pas besoin de vérifier les types dynamiquement lors de l'exécution (il vérifie avant de s'exécuter).
De même, les langues compilées sont plus rapides au moment de l'exécution car le code a déjà été traduit au lieu de devoir «l'interpréter» / le traduire à la volée.
Notez que les langues compilées et typées statiquement auront un délai avant de s'exécuter pour la traduction et la vérification de type, respectivement.
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" dans la mesure où il ne permet pas les erreurs de type n'importe où dans votre programme et empêche souvent les variables de changer de type, ce qui se défend davantage contre les erreurs involontaires.
num = 2
num = '3' // ERROR
La frappe dynamique est plus flexible, ce que certains apprécient. Il permet généralement aux variables de changer de type, ce qui peut entraîner des erreurs inattendues.
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 lors de l'exécution)
Exemples: C, C ++, Java
Langages typés dynamiquement : 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;
un peut prendre n'importe quel type de valeurs lors de l'exécution)
Exemples: Ruby, Python.
Vérification de type des langages typés au moment de la compilation et le type ne peut PAS changer. (Ne soyez pas mignon avec les commentaires de conversion de type, une nouvelle variable / référence est créée).
La vérification de type des langages typés dynamiquement au moment de l'exécution et le type d'une variable PEUVENT être modifiés au moment de l'exécution.
Définitions douces et simples, mais adaptées au besoin: les langages typés statiquement lient le type à une variable pour toute sa portée (Seg: SCALA) Les langages typés dynamiquement lient le type à la valeur réelle référencée par une variable.
Les langages à typage statique comme C ++, Java et les langages à typage dynamique comme Python ne diffèrent qu'en termes d'exécution du type de la variable. Les langages à typage statique ont un type de données statique pour la variable, ici le type de données est vérifié pendant la compilation, donc le débogage est beaucoup plus simple ... tandis que le typage dynamique langages à ne font pas la même chose, le type de données est vérifié qui exécute le programme et donc le le débogage est un peu difficile.
De plus, ils ont une très petite différence et peuvent être liés à des langues fortement typées et faiblement typées . Une langue fortement typée ne vous permet pas d'utiliser un type comme un autre, par exemple. C et C ++ ... alors que les langages faiblement typés permettent par exemple de python
Typé statiquement
Les types sont vérifiés avant l'exécution afin que les erreurs puissent être détectées plus tôt.
Exemples = c ++
Typé dynamiquement
Les types sont vérifiés lors de l'exécution.
Exemples = Python
Langages typés statiques (le compilateur résout les appels de méthode et compile les références):
Langages typés dynamiques (décisions prises dans le programme en cours):
le langage typé dynamiquement permet de prototyper rapidement les concepts d'algorithme sans avoir à réfléchir sur les types de variables à utiliser (ce qui est une nécessité dans le langage typé statiquement ).
Typage statique: les langages tels que Java et Scala sont typés statiquement.
Les variables doivent être définies et initialisées avant d'être utilisées dans un code.
par ex. int x; x = 10;
System.out.println (x);
Typage dynamique: Perl est un langage typé dynamique.
Les variables n'ont pas besoin d'être initialisées avant d'être utilisées dans le code.
y = 10; utiliser cette variable dans la dernière partie du code
$
), array ( @
) et hash ( %
). Le type d'une variable en Perl est connu au moment de la compilation et reste le même pour le reste de la durée de vie des variables.