В динамически типизированной системе значения имеют типы во время выполнения, а переменные и функции - нет. В статически типизированной системе переменные и функции имеют типы, известные и проверенные во время компиляции. Например, в Python x
может быть что угодно ; во время выполнения, если это 1
число, а если это - "foo"
строка. Вы бы знали только, какой тип x
был во время выполнения, и он может отличаться при каждом запуске программы. На таком языке, как Java, вы написали int x
бы, если x
бы это было число, и знали бы, что во время компиляции это x
всегда должно быть int
.
«Явный» и «неявный» типы относятся к системам статических типов. Определяющей характеристикой статической системы является то, что типы известны во время компиляции, но не обязательно, что они должны быть записаны. В Java типы являются явными - вы должны записать их. Поэтому в Java метод может выглядеть примерно так:
public int foo(String bar, Object baz) { ... }
Типы известны как во время компиляции (статические), так и записаны (явные). Однако есть также языки, которые не заставляют вас писать тип. Они могут определить тип функции по ее телу и то, как она используется. Примером может служить OCaml, где вы можете написать что-то вроде:
let foo x = x + 1
Так как вы использовали +
, OCaml может выяснить, что x
должно быть int
все самостоятельно. Таким образом, тип foo
( foo : int -> int
) будет известно во время компиляции, так же , как , например Java. Это полностью статично. Однако, поскольку компилятор может самостоятельно определять, какими должны быть типы, вам не нужно их самим писать: они неявные.
Короче говоря, является ли система типов явной или неявной, это свойство статических систем. Это совершенно другой вопрос по сравнению с тем, является ли система типов динамической или статической.
Часто у вас есть системы типов, которые иногда являются явными, а иногда и неявными.
Например, я считаю, что C # позволяет вывести типы, используя var
ключевое слово. Поэтому вместо того, чтобы писать int x = 10
, вы можете написать, var x = 10
и компилятор выяснит, что x
это должно быть int
. C ++ делает нечто подобное с auto
. Эти системы обычно являются явными, но имеют некоторый вывод.
С другой стороны, существуют системы, которые обычно неявны, но иногда вынуждают вас выписывать сигнатуру типа. Haskell - отличный пример. В большинстве случаев Haskell может определить типы для вас. Однако иногда вы можете написать код, который неоднозначен, например show . read
, когда Haskell не может самостоятельно определить типы. В этом случае вы будете вынуждены явно указать тип либо show
или read
. Кроме того, некоторые более продвинутые возможности системы типов (такие как полиморфизм ранга n) делают вывод неразрешимым, то есть он не гарантированно останавливается. Это означает, что код, использующий эту функцию, часто нуждается в явных сигнатурах типов.