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

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

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

  • Strong / Weak Typing – о том, как строго различаются типы (например, пытается ли язык делать неявное преобразование из строк в числа).

Более подробную информацию см. На wiki-странице .

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

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

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

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

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

Например, в 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. 

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

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

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

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

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

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

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

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

Сильный и слабый ввод:

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

Статические и динамические типы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Type_system
  • Strong_and_weak_typing
  • Категория: Statically_typed_programming_languages
  • Категория: Dynamically_typed_programming_languages

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

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

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

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

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

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

 String a = "123" int b = (int)a; 

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

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

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

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

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

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

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

  • В чем разница между «методом classа» и «статическим методом»?
  • В чем разница между аргументом и параметром?
  • Разница между DTO, VO, POJO, JavaBeans?
  • Что такое reflection и почему оно полезно?
  • Как вы читаете! Важно в CSS?
  • Что такое определения, декларации и назначения C ++?
  • Что такое null в Java?
  • ?? Null Coalescing Operator -> Что означает коалесцирование?
  • Что такое инъекция зависимости?
  • В чем разница между абстрактным деревом синтаксиса и деревом синтаксиса бетона?
  • Что такое переменная cls, используемая в classах Python?
  • Давайте будем гением компьютера.