Статический / Динамический против Сильный / Слабый

319

Я вижу эти термины повсеместно в программировании, и у меня есть смутное представление о том, что они имеют в виду. Поиск показывает, что на самом деле такие вещи задавались по всему переполнению стека. Насколько я знаю, статическая / динамическая типизация в языках слегка отличается от строгой / слабой типизации, но в чем заключается это отличие, ускользает от меня. Различные источники, кажется, используют разные значения или даже взаимозаменяемо. Я не могу найти где-то, что говорит об обоих и на самом деле излагает разницу. Что было бы неплохо, если бы кто-то мог, пожалуйста, четко изложить это здесь для меня и остального мира.

Дэн Ревелл
источник

Ответы:

423
  • Статический / Динамический Typing о когда информация о типе приобретенными (либо во время компиляции или во время выполнения)

  • Сильная / слабая типизация заключается в том, как строго различаются типы (например, пытается ли язык выполнить неявное преобразование из строк в числа).

Смотрите вики-страницу для более подробной информации.

Dario
источник
7
В Википедии есть все ответы. Почему я не наткнулся на это уже, я не знаю.
Дэн Ревелл
31
Обидно, что многие не знают, что статический / динамический это что-то еще, кроме сильного / слабого ... Это действительно спасло бы некоторую предвзятость и обсуждение.
Dykam
10
Существуют разные степени «слабости типа». Сильно типизированный язык может пытаться преобразовать строки в числа. С другой стороны, HyperTalk (язык, который я использовал десятилетия назад) был настолько слабо типизирован, что "12" + "34"будет равен "46", но "12" + "34Q"будет равен "1234Q"[к счастью, можно написать, "12" & "34"если захочется объединение]. Любопытно, что переменные, содержащие числа, сохраняли их как числа с плавающей запятой двойной точности, и математика для таких переменных использовала значения с плавающей запятой без вычисления строки, но не было никакого способа спросить, является ли переменная строкой или числом.
суперкат
9
@kittylyst Я не вижу, где этот ответ предполагает, что сильный является синонимом статики
Пит
4
++ для (примерно) однострочных определений.
JamesFaix
211

Вы обнаружили слабое место в терминологии, которую любители используют для разговоров о языках программирования. Не используйте термины «сильная» и «слабая» типизация , потому что они не имеют общепризнанного технического значения. Напротив, статическая типизация означает, что программы проверяются перед выполнением , и программа может быть отклонена до ее запуска. Динамическая типизация означает, что типы значений проверяются во время выполнения , а плохо напечатанная операция может привести к остановке программы или иным образом сигнализировать об ошибке во время выполнения . Основной причиной статической типизации является исключение программ, которые могут иметь такие «ошибки динамического типа».

Строгая типизация обычно означает, что в системе типов нет лазеек, в то время как слабая типизация означает, что система типов может быть подорвана (аннулируя любые гарантии). Термины часто используются неправильно для обозначения статической и динамической типизации. Чтобы увидеть разницу, подумайте о C: язык проверяется на тип во время компиляции (статическая типизация), но существует множество лазеек; вы можете в значительной степени привести значение любого типа к другому типу того же размера - в частности, вы можете свободно приводить типы указателей. Паскаль был языком, который предназначался для строгой типизации, но, как известно, имел непредвиденную лазейку: вариант записи без тега.

Реализации строго типизированных языков часто приобретают лазейки со временем, обычно, так что часть системы времени выполнения может быть реализована на языке высокого уровня. Например, в Objective Caml есть функция с именем, Obj.magicкоторая во время выполнения просто возвращает свой аргумент, но во время компиляции преобразует значение любого типа в значение любого другого типа. Мой любимый пример - Modula-3, дизайнеры которого назвали свою конструкцию для литья типов LOOPHOLE.

Сказав это, вы не можете рассчитывать на то, что два человека будут использовать слова «сильный» и «слабый» одинаково. Так что избегай их.

Норман Рэмси
источник
31
(+1) за ваше предложение избегать терминов "сильный" и "слабый".
Нико
1
Согласился, просто читал книгу Джона Скита, и это тот же самый ответ, отмеченный там.
Беннет Йейтс
Насколько мне известно, в Java также есть эти лазейки, но он все еще считается языком со строгой типизацией, поэтому я полагаю, что это придает больший вес вашему совету избегать терминов "сильный" и "слабый".
doubleOrt
74

Проще говоря, так: в языке со статической типизацией тип является статическим , то есть, когда вы устанавливаете переменную для типа, вы НЕ МОЖЕТЕ изменить ее. Это связано с тем, что типизация связана с переменной, а не со значением, к которому она относится.

Например в Java:

String str = "Hello";  //statically typed as string
str = 5;               //would throw an error since java is statically typed

В то время как в динамически типизированном языке тип является динамическим , то есть после того, как вы установите переменную для типа, вы МОЖЕТЕ изменить ее. Это связано с тем, что типизация связана со значением, а не с переменной.

Например в Python:

str = "Hello" # it is a string
str = 5       # now it is an integer; perfectly OK

С другой стороны, строгая / слабая типизация в языке связана с неявным преобразованием типов (частично взято из ответа @ Dario):

Например в Python:

str = 5 + "hello" 
# would throw an error since it does not want to cast one type to the other implicitly. 

тогда как в PHP:

$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0 
// PHP is weakly typed, thus is a very forgiving language.

Статическая типизация позволяет проверять правильность типа во время компиляции. Статически типизированные языки обычно компилируются, а динамически типизированные языки интерпретируются. Следовательно, динамически типизированные языки могут проверять типизацию во время выполнения.

Мехмет
источник
2
отличный ответ, и слава за использование конкретных примеров.
Джулиан А.
3
Вот почему PHP нужно использовать с большой осторожностью.
Али Гаджани
1
Примеры языка действительно полезны. Очень признателен.
Дж Маллен
В этом смысле будет ли Java очень слабо типизирован, потому что вы можете объединять не-строки со строками, а также из-за автоматической распаковки / упаковки?
Стивен Пол
1
@ StephenPaul, вы правы, мой ответ может быть понят таким образом, и это не так. Я использовал конкатенацию ради простоты, но на самом деле сильная / слабая сторона заключается в неявном преобразовании типов самой переменной.
Мехмет
20

Слабая типизация означает, что тип объекта может меняться в зависимости от контекста. Например, в слабо типизированном языке строка «123» может рассматриваться как число 123, если вы добавите к нему другое число. Примерами языков со слабой типизацией являются bash, awk и PHP.

Другой тип слабо типизированного языка - C, где данные по адресу памяти могут быть обработаны как другой тип путем приведения.

В строго типизированном языке тип объекта не изменяется - int всегда является int и попытка использовать его в качестве строки приведет к ошибке. И Java, и Python строго типизированы.

Разница между динамической и статической типизацией заключается в применении правил типа. В статически типизированном языке тип каждой переменной и параметра должен быть объявлен в источнике и применяется во время компиляции. В динамически типизированном языке типы проверяются только тогда, когда они используются во время выполнения. Таким образом, Java статически типизирован, а Python динамически типизирован.

Однако границы могут быть немного размытыми время от времени. Например, хотя Java является статически типизированной, каждый раз, когда вы используете отражение или приведение (например, при использовании контейнеров объектов), они откладывают проверку типа до времени выполнения.

Точно так же большинство строго типизированных языков все равно будут автоматически конвертировать между целыми числами и числами с плавающей точкой (и в некоторых языках с точностью до BigInts)

Дейв Кирби
источник
1
Я не могу согласиться с этим предложением. «В статически типизированном языке тип каждой переменной и параметра должен быть объявлен в источнике» - в SML типы переменных не должны объявляться (как бы они ни проверялись). Допустим, функция fпринимает аргумент x( fun f(x)) [**, поэтому типы не объявляются **], а тело функции - x+1. Без объявленных типов компилятор выяснит, что xдолжно быть int. - fun f x = x + 1; val f = fn : int -> int
Филипп Бартузи
Что касается C, приведение не против строгой типизации, но C позволяет добавлять разные типы, не приводя также и приведение, например:5 + 'c' // OK
mehmet
3
@mehmet: в C символьные значения находятся в целочисленной области, поэтому конкретный пример не нарушает безопасность типов. 'c' - просто синтаксический сахар для 99. C не имеет выделенного типа символов.
Питер Леверин
Питер Леверин: правильно, я должен был привести лучший пример. К сожалению, прошло уже почти 20 лет с тех пор, как я не прикасался к C :)
mehmet
1
С не слабо типизированный язык . Просто Java, C # и т. Д. Являются более строго типизированными языками по сравнению с C. Подробнее читайте здесь - en.wikipedia.org/wiki/Strong_and_weak_typing Если вы проверяете определение «слабо» типизированного языка, тогда «слабо» типизированные языки это те, в которых вы можете выполнять любой тип преобразования, например, int может быть «неявно» преобразован или приведен к строке, теперь подумайте сами, возможно ли это в C или нет?
hagrawal
15

Сегодня, исследуя эту тему, я наткнулся на эту замечательную статью http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html Она прояснила много вещи для меня, и я подумал, что это может добавить к некоторым из великих ответов выше.

Сильный и слабый набор текста:

Вероятно, наиболее распространенным способом классификации систем типов является «сильный» или «слабый». Это прискорбно, поскольку эти слова почти не имеют никакого значения. В ограниченной степени возможно сравнить два языка с очень похожими системами типов и назначить один из них более сильным из этих двух систем. Кроме того, слова вообще ничего не значат.

Статический и Динамический Типы

Это почти единственная распространенная классификация систем типов, которая имеет реальное значение. На самом деле, его значение часто недооценивают [...] Динамические и статические системы типов - это две совершенно разные вещи, цели которых частично перекрываются.

Система статических типов - это механизм, с помощью которого компилятор проверяет исходный код и присваивает метки (называемые «типами») частям синтаксиса, а затем использует их, чтобы сделать вывод о поведении программы. Система динамических типов - это механизм, с помощью которого компилятор генерирует код для отслеживания вида данных (по совпадению, также называемого их «типом»), используемых программой. Использование одного и того же слова «тип» в каждой из этих двух систем, конечно, не совсем случайно; все же это лучше всего понято как имеющее своего рода слабое историческое значение. Большая путаница возникает в результате попытки найти мировоззрение, в котором «тип» действительно означает одно и то же в обеих системах. Это не так.

Явные / неявные типы:

Когда эти термины используются, они относятся к степени, в которой компилятор рассуждает о статических типах частей программы. Все языки программирования имеют некоторую форму рассуждений о типах. У некоторых есть больше чем у других. ML и Haskell имеют неявные типы, в которых не требуется (или очень мало, в зависимости от используемого языка и расширений) объявлений типов. Java и Ada имеют очень явные типы, и каждый постоянно объявляет типы вещей. Все вышеперечисленное имеет (относительно, по сравнению, например, с C и C ++) системы с сильным статическим типом.

Gonz
источник
8

Из Прагматики языка программирования Скотта , 3-е издание стр. 291, мы

Проверка типов - это процесс обеспечения соблюдения программой правил совместимости типов в языке. Нарушение правил известно как столкновение типов. Говорят, что язык строго типизирован, если он запрещает таким образом, чтобы реализация языка могла принудительно применять любое действие к любому объекту, который не предназначен для поддержки этой операции. Язык называется статически типизированным, если он строго типизирован и проверка типов может выполняться во время компиляции. В самом строгом смысле этого слова, несколько языков статически типизированы. На практике этот термин часто применяется к языкам, на которых большая часть проверки типов может выполняться во время компиляции, а остальные могут выполняться во время выполнения.

Несколько примеров: Ada строго типизирован и по большей части статически типизирован (определенные ограничения типов должны проверяться во время выполнения). Реализация на Паскале также может выполнять большую часть проверки типов во время компиляции, хотя язык не является строго строго типизированным: записи вариантов без тегов (которые будут обсуждаться в Разделе 7.3.4) являются его единственной лазейкой. C89 значительно более типизирован, чем его предшественники, но все же значительно менее типизирован, чем Паскаль. Его лазейки включают объединения, подпрограммы с переменным числом параметров и функциональную совместимость указателей и массивов (будет обсуждаться в разделе 7.7.1). Реализации C редко проверяют что-либо во время выполнения.

Динамическая (во время выполнения) проверка типов является одной из форм позднего связывания и, как правило, встречается в языках, которые также задерживают другие проблемы до времени выполнения. Lisp и Smalltalk динамически (хотя и сильно) типизированы. Большинство языков сценариев также динамически типизируются; некоторые (например, Python и Ruby) строго типизированы. Языки с динамической областью видимости обычно динамически типизированы (или вообще не типизированы): если компилятор не может идентифицировать объект, к которому относится имя, он обычно также не может определить тип объекта.

Таким образом, простыми словами, статическая / динамическая типизация относится ко времени, когда происходит проверка типов: время компиляции для статической типизации и время выполнения для динамических языков. Аналогично, строгая / слабая типизация относится к тому, насколько агрессивно язык применяет свою систему типов.

Я попытался перевести описание Скотта в хорошую диаграмму, которую я разместил ниже.

Статическая / динамическая - сильная / слабая плоскость набора текста

Эван Росика
источник
5

Я думаю, что другие коллеги сделали хорошую работу, особенно. объясняя разницу между статической и динамической типизацией. Но что касается сильной и слабой типизации, то следует сказать, что существуют разные понимания / взгляды.

Вот два примера:

  • Некоторые говорят, что Хаскель строго типизирован, потому что вам не разрешено делать какие-либо преобразования типов.

  • Другие (например, взгляд Дарио) говорят, что язык, который позволяет неявно конвертировать из строки в число специально, слабо типизирован, но даже другие называют это просто утиной типизацией.

Оба утверждения подчеркивают не противоположные крайности системы типов, а совершенно разные аспекты. Поэтому я присоединяюсь к мнению г-на Рэмси не использовать термины «сильный» и «слабый» для различения систем типов.

Нико
источник
5

Статически v / s динамически типизированные языки

  • Статически типизированные языки - это те языки, в которых проверка типов выполняется во время компиляции, поэтому это также означает, что в статически типизированных языках каждая переменная имеет тип, и он не изменяется в течение курса. Теперь, напротив, динамически типизированные языки - это те, в которых проверка типов выполняется во время выполнения, и нет проверки типов во время компиляции, так что это также означает, что в динамически типизированных языках может быть или не быть тип, связанный с переменными и если тип связан, то это может быть универсальный тип, такой как «var» в JS, который подходит как для строки, так и для числа.
    • «Реализации языков с динамической проверкой типов обычно связывают каждый объект времени выполнения с тегом типа (т. Е. Ссылкой на тип), содержащим информацию о его типе. Эта информация о типе среды выполнения (RTTI) также может использоваться для реализации динамической отправки, позднего связывания, приведения вниз, отражения и аналогичных функций ».
  • Даже если язык статически типизирован, все же он может иметь некоторую динамически типизированную функцию, что в основном означает, что некоторая проверка типов также выполняется во время выполнения. Это полезно при приведении типов.
    • «Ряд полезных и распространенных функций языка программирования невозможно проверить статически, например, при понижении частоты. Таким образом, многие языки будут иметь как статическую, так и динамическую проверку типов; средство проверки статического типа проверяет, что оно может, а средство динамической проверки - все остальное ».
  • «Некоторые языки позволяют писать код, который не является типобезопасным. Например, в C программисты могут свободно приводить значения между любыми двумя типами, которые имеют одинаковый размер ».
  • Преимущество «статически» типизированных языков заключается в том, что:
    • Поскольку большая часть проверки типов выполняется во время компиляции, интерпретатор или среда выполнения могут работать на полной скорости, не беспокоясь о типах.
    • Это приводит к меньшему количеству исключений во время выполнения или ошибок, связанных с типом, потому что большая часть проверки типов выполняется во время компиляции.
  • Преимущество «динамически» типизированных языков заключается в том, что:
    • Они могут помочь в чрезвычайно быстром прототипировании, поскольку разработчику не нужно понимать систему типов, поэтому dev может свободно создавать переменные и запускать их, что приводит к очень быстрому прототипированию.
  • Список статически и динамически типизированных языков :
    • Статически:
      • Ява
      • C (C - статически типизированный язык, но менее «строго» типизированный по сравнению с Java, поскольку он допускает более неявные преобразования)
      • C ++
      • C #
    • Динамически:
      • PERL
      • PHP
      • питон
      • JavaScript
      • Рубин
  • Проверка типов является важной функцией безопасности. Предположим, что нет проверки типов, и метод принимает объект типа «BankAccount», у которого есть метод, называемый «creditAccount (BankAccountDetails)», теперь во время выполнения, если нет проверки типов, тогда я могу передать собственный объект класс, который имеет тот же метод «creditAccount (BankAccountDetails)», и он будет выполнен, учитывая, что мы говорим об объектно-ориентированном языке, потому что ООП поддерживает «полиморфизм», а здесь мы обсуждаем не что иное, как «полиморфизм». Таким образом, в основном объектно-ориентированный язык (что означает, что он поддерживает «полиморфизм»), который не имеет строгой проверки типов, может привести к проблемам с безопасностью.

Сильно v / s слабо типизированные языки

  • Строго типизированные языки - это те языки, в которых неявные преобразования не допускаются в случае потери точности. Например, в Java вы можете привести «int к long», потому что нет потери точности, но вы не можете «неявно» привести «long к int», потому что будет потеря точности. Напротив, в слабо типизированных языках допускаются неявные преобразования даже в случае потери точности.
  • Я думаю, что динамически типизированный язык также может быть строго типизированным языком, если «во время выполнения» он не допускает неявных преобразований, в которых наблюдается потеря точности.

Хорошие дальнейшие чтения

hagrawal
источник
Вы цитировали «сейчас во время выполнения, если нет проверки типов, тогда я могу передать объект моего собственного класса, который имеет тот же метод« creditAccount (BankAccountDetails) »- если вы уже превзошли механизм, который мог заблокировать вас от передачи объекта тогда как проверка типов
помешает
@AseemYadav Что вы подразумеваете под "*, если вы уже превзошли механизм, который мог заблокировать вас от прохождения объекта *"?
Хагравал
как вы упомянули, это важная функция безопасности, а также то, что вы можете передавать объект своего собственного класса тем же методом, поэтому для меня это означает, что это кажется уязвимостью только тогда, когда вы пытаетесь проникнуть в чужой код и если вы говорите в контексте кода, который принадлежит вам, а не о производительности, а не о безопасности, не так ли?
Асем Ядав
В этом нет никакого аспекта производительности, вы должны увидеть его в контексте полиморфизма, тогда вы сможете понять его аспект безопасности, я упоминал об этом в том же параграфе.
Хагравал
1

В статически типизированных языках обычно требуется объявлять типы переменных, которые затем проверяются во время компиляции, чтобы уменьшить количество ошибок. Слово «статический» в «статически типизированном» относится к «статическому анализу кода», который представляет собой процесс проверки кода перед его выполнением. Хотя для статически типизированного языка возможно вывести тип переменной из правой части выражения или фактических параметров, на практике большинство статически типизированных языков требуют, чтобы типы переменных были явно объявлены.

Динамически типизированные языки, как правило, не требуют, чтобы объявления переменных имели типы, и они выводят типы переменных на основе типа, вычисленного в результате оценки правой части каждого оператора присваивания или фактических параметров для вызова функции. Поскольку переменной может быть присвоено несколько назначений в течение срока ее службы, ее тип может меняться со временем, и именно поэтому она называется «динамически типизированной». Кроме того, среда выполнения должна отслеживать текущий тип для каждой переменной, поэтому тип связан со значением, а не с объявлением переменной. Это можно считать системой информации о типе среды выполнения (RTTI).

Элементы статически и динамически типизированных языков могут быть объединены. Например, C # поддерживает как статически, так и динамически типизированные переменные, а объектно-ориентированные языки обычно поддерживают понижающую иерархию типов. Языки со статической типизацией обычно предоставляют различные способы обойти проверку типов, например, используя приведение, отражение и динамический вызов.

Сильная и слабая типизация означает непрерывность того, насколько язык пытается предотвратить ошибки из-за использования переменной, как если бы это был один тип, тогда как на самом деле это другой тип. Например, и C, и Java являются статически типизированными языками, однако в Java используется гораздо более строгая проверка типов, чем в C. Следующий код C рад компилировать и запускать и помещает случайное значение в переменную b во время выполнения, скорее всего, вызывая ошибка:

char *a = "123";
int b = (int)a;

Эквивалентный Java-код вызовет ошибку компиляции, которая обычно предпочтительнее:

String a = "123"
int b = (int)a;
Опасность
источник