Dans un système typé dynamiquement, les valeurs ont des types à l'exécution, mais pas les variables et les fonctions. Dans un système typé statiquement, les variables et les fonctions ont des types connus et vérifiés au moment de la compilation. Par exemple, en Python x
peut être n'importe quoi ; à l'exécution, si c'est 1
un nombre et s'il l'est "foo"
, c'est une chaîne. Vous ne sauriez que quel type x
était à l'exécution, et il pourrait être différent à chaque fois que vous exécutez le programme. Dans un langage comme Java, vous écririez int x
if x
devait être un nombre, et vous sauriez au moment de la compilation que cela x
doit toujours être un int
.
Les types "explicites" et "implicites" se réfèrent tous deux à des systèmes de types statiques . La caractéristique qui définit un système statique est que les types sont connus au moment de la compilation, mais pas nécessairement qu'ils doivent être écrits. En Java, les types sont explicites - vous devez les écrire. Ainsi, en Java, une méthode pourrait ressembler à quelque chose comme:
public int foo(String bar, Object baz) { ... }
Les types sont à la fois connus au moment de la compilation (statiques) et écrits (explicites). Cependant, il y a aussi des langues qui ne pas vous forcer à écrire le type out. Ils peuvent déduire le type d'une fonction de son corps et comment elle est utilisée. Un exemple serait OCaml, où vous pouvez écrire quelque chose comme:
let foo x = x + 1
Depuis que vous l'avez utilisé +
, OCaml peut comprendre que cela x
doit être un int
tout seul. Le type de foo
( foo : int -> int
) est donc connu au moment de la compilation, tout comme l'exemple Java. C'est entièrement statique. Cependant, puisque le compilateur peut déterminer ce que les types doivent être par lui-même, vous n'avez pas à les écrire vous-même: ils sont implicites.
En bref: si un système de type est explicite ou implicite est une propriété des systèmes statiques . C'est une question complètement différente de savoir si un système de type est dynamique ou statique.
Souvent, vous avez des systèmes de types qui sont parfois explicites et parfois implicites.
Par exemple, je pense que C # vous permet de déduire des types à l'aide du var
mot clé. Donc, au lieu d'écrire int x = 10
, vous pouvez écrire var x = 10
et le compilateur doit comprendre que cela x
doit être un int
. C ++ fait quelque chose de similaire avec auto
. Ces systèmes sont généralement explicites mais ont une certaine inférence.
D'un autre côté, il existe des systèmes qui sont généralement implicites mais vous obligent parfois à écrire une signature de type. Haskell en est un excellent exemple. La plupart du temps, Haskell peut déduire les types pour vous. Cependant, parfois, vous pouvez écrire du code ambigu comme show . read
, où Haskell ne peut pas comprendre les types par lui-même. Dans ce cas, vous seriez obligé de spécifier explicitement le type de show
ou read
. De plus, certaines fonctionnalités plus avancées du système de types (comme le polymorphisme de rang n) rendent l'inférence indécidable - c'est-à-dire qu'il n'est pas garanti qu'elle s'arrête. Cela signifie que le code utilisant cette fonctionnalité nécessite souvent des signatures de type explicites.
statique vs dynamique décrit quand les types sont vérifiés (plus ou moins au moment de la compilation ou au moment de l'exécution)
nominal vs structurel décrit quand deux types sont considérés comme identiques.
(Et il existe des variantes, la plus connue est la variante du typage structurel qui ne prend en compte que ce qui est utilisé au lieu du type entier appelé typage canard).
Les quatre combinaisons (nominal statique, structurel statique, nominal dynamique, structurel dynamique) sont possibles, et les langues ne sont souvent pas purement dans une classe mais ont des aspects qui sont dans d'autres.
Par exemple, les systèmes de types de C ++ sont statiques, principalement nominaux mais structurels lorsque vous considérez les modèles (et vous pouvez considérer une partie des problèmes liés aux concepts en C ++ comme un conflit entre ceux qui souhaitent passer du typage canard à une forme complète de typage structurel et ceux qui veulent passer à la frappe nominale). Et l'utilisation des classes et de l'héritage permet d'utiliser un typage dynamique et nominal dans certains cas.
Langage qu'un système de type dynamique utilise souvent le typage structurel, mais CLOS comme aspects nominaux.
la source
Ce n'est généralement pas le cas. Le typage structurel signifie qu'il
B
s'agit d'un sous-type deA
s'il peut satisfaireA
l'interface de. Cela signifie généralement avoir des membres du même nom; pas seulement la même structure en mémoire.Cela diffère du typage nominatif qui nécessite que les super-types soient spécifiés lors de la déclaration.
la source
La meilleure explication que j'ai vue de la distinction entre (en fait la subsomption des) systèmes de type dynamique et statique est dans cet article de blog de Bob Harper:
Son principal point pourrait être résumé comme suit:
la source