Это часто неправильно понимают, поэтому позвольте мне прояснить это.
Статическая / динамическая печать
Статическая типизация - это место, где тип связан с переменной . Типы проверяются во время компиляции.
Динамическая типизация - это место, где тип связан со значением . Типы проверяются во время выполнения.
Например, в Java:
String s = "abcd";
s
будет "навсегда" быть String
. В течение своей жизни он может указывать на различные String
с (поскольку s
является ссылкой в Java). Может иметь значение null
, но никогда не будет ссылаться на Integer
или List
. Это статическая типизация.
В PHP:
$s = "abcd"; // $s is a string
$s = 123; // $s is now an integer
$s = array(1, 2, 3); // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class
Это динамическая типизация.
Сильный / слабый набор текста
(Изменить оповещение!)
Сильное печатание - это фраза, которая не имеет общепринятого значения. Большинство программистов, которые используют этот термин для обозначения чего-то иного, чем статическая типизация, используют его, чтобы подразумевать, что существует компиляция типов, которая обеспечивается компилятором. Например, CLU имеет систему строгого типа, которая не позволяет клиентскому коду создавать значение абстрактного типа, за исключением использования конструкторов, предоставляемых этим типом. C имеет довольно сильную систему типов, но она может быть «подорвана» до некоторой степени, потому что программа всегда может привести значение одного типа указателя к значению другого типа указателя. Так, например, в C вы можете взять значение, возвращаемое malloc()
, и весело преобразовать его в FILE*
, и компилятор не будет пытаться остановить вас - или даже предупредить вас, что вы делаете что-то хитрое.
(В первоначальном ответе говорилось что-то о значении «неизменяемый тип во время выполнения». Я знал многих разработчиков языков и разработчиков компиляторов и не знал ни одного, который бы говорил о значении, изменяющем тип во время выполнения, за исключением, возможно, очень продвинутого исследование систем типов, где это известно как «проблема сильного обновления».)
Слабая типизация подразумевает, что компилятор не приводит к дисквалификации при вводе или, возможно, принудительное использование может быть легко подорвано.
Оригинал этого ответа смешал слабую типизацию с неявным преобразованием (иногда также называемым "неявным продвижением"). Например, в Java:
String s = "abc" + 123; // "abc123";
Этот код является примером неявного продвижения: 123 неявно преобразуется в строку перед объединением с "abc"
. Можно утверждать, что компилятор Java переписывает этот код как:
String s = "abc" + new Integer(123).toString();
Рассмотрим классическую проблему PHP "начинается с":
if (strpos('abcdef', 'abc') == false) {
// not found
}
Ошибка здесь в том, что strpos()
возвращает индекс совпадения, будучи 0. 0 приведен к логическому false
и, таким образом, условие на самом деле истинно. Решение состоит в том, чтобы использовать ===
вместо ==
, чтобы избежать неявного преобразования.
Этот пример иллюстрирует, как комбинация неявного преобразования и динамической типизации может сбить программистов с пути.
Сравните это с Ruby:
val = "abc" + 123
, что является ошибкой во время выполнения, поскольку в Ruby объект 123 не неявно преобразуется только потому, что он передается методу +
. В Ruby программист должен сделать преобразование явным:
val = "abc" + 123.to_s
Хорошая иллюстрация здесь - сравнение PHP и Ruby. Оба являются динамически типизированными языками, но в PHP есть много неявных преобразований, а в Ruby (возможно, удивительно, если вы не знакомы с ним) нет.
Статический / Динамический против Сильный / Слабый
Дело в том, что статическая / динамическая ось не зависит от сильной / слабой оси. Люди путают их, вероятно, отчасти потому, что сильная и слабая типизация не только менее четко определены, но и нет единого мнения о том, что именно подразумевается под сильной и слабой. По этой причине сильная / слабая типизация является скорее оттенком серого, чем черного или белого.
Итак, чтобы ответить на ваш вопрос: еще один способ взглянуть на это, который в основном правильный, - это сказать, что статическая типизация - это безопасность типов во время компиляции, а строгая - это безопасность типов во время выполнения.
Причина этого в том, что переменные в статически типизированном языке имеют тип, который должен быть объявлен и может быть проверен во время компиляции. В языке со строгим типом есть значения, которые имеют тип во время выполнения, и программисту трудно подорвать систему типов без динамической проверки.
Но важно понимать, что язык может быть статическим / сильным, статическим / слабым, динамическим / сильным или динамическим / слабым.