In un sistema tipizzato dinamicamente, i valori hanno tipi in fase di esecuzione ma variabili e funzioni no. In un sistema tipicamente statico, variabili e funzioni hanno tipi conosciuti e controllati in fase di compilazione. Ad esempio in Python xpuò essere qualsiasi cosa ; in fase di esecuzione, se è 1un numero e se lo è "foo", è una stringa. Sapresti solo quale tipo xera in fase di esecuzione e potrebbe essere diverso ogni volta che eseguivi il programma. In una lingua come Java, scriveresti int xse xdovesse essere un numero e sapresti in fase di compilazione che xdeve essere sempre un int.
I tipi "espliciti" e "impliciti" si riferiscono entrambi a sistemi di tipo statico . La caratteristica che definisce un sistema statico è che i tipi sono noti al momento della compilazione, ma non necessariamente che devono essere scritti. In Java, i tipi sono espliciti: devi scriverli. Quindi in Java, un metodo potrebbe assomigliare a:
public int foo(String bar, Object baz) { ... }
I tipi sono entrambi noti al momento della compilazione (statici) e scritti (espliciti). Tuttavia, ci sono anche lingue che non ti costringono a scrivere il tipo. Possono inferire il tipo di una funzione dal suo corpo e come viene usata. Un esempio potrebbe essere OCaml, dove puoi scrivere qualcosa del tipo:
let foo x = x + 1
Dal momento che hai usato +, OCaml può capire che xdeve essere un inttutto da solo. Quindi il tipo di foo( foo : int -> int) è noto al momento della compilazione, proprio come nell'esempio Java. È completamente statico. Tuttavia, dal momento che il compilatore può capire quali devono essere i tipi da soli, non è necessario scriverli da soli: sono impliciti.
In breve: se un sistema di tipo è esplicito o implicito è una proprietà dei sistemi statici . È una domanda completamente diversa dal fatto che un sistema di tipo sia dinamico o statico.
Spesso hai sistemi di tipi che sono a volte espliciti e talvolta impliciti.
Ad esempio, credo che C # ti permetta di inferire i tipi usando la varparola chiave. Quindi, invece di scrivere int x = 10, puoi scrivere var x = 10e il compilatore scopre che xdeve essere un int. C ++ fa qualcosa di simile con auto. Questi sistemi sono di solito espliciti ma hanno qualche deduzione.
D'altra parte, ci sono sistemi che sono solitamente impliciti ma a volte ti costringono a scrivere una firma di tipo. Haskell è un ottimo esempio. Il più delle volte, Haskell può inferire i tipi per te. Tuttavia, a volte puoi scrivere un codice ambiguo show . read, in cui Haskell non riesce a capire i tipi da solo. In questo caso, saresti costretto a specificare esplicitamente il tipo di uno showo read. Inoltre, alcune caratteristiche più avanzate del sistema di tipi (come il polimorfismo di rango n) rendono l'inferenza indecidibile, cioè non è garantito che si fermi. Ciò significa che il codice che utilizza questa funzione richiede spesso firme di tipo esplicite.