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.