В чем разница между языком со строгой типизацией и языком со статической типизацией?

Кроме того, одно подразумевает другое?


person JDelage    schedule 22.04.2010    source источник
comment
Обратите внимание на почти дублирующийся на stackoverflow.com/questions/2351190/   -  person Norman Ramsey    schedule 23.04.2010
comment
Tcl строго типизирован. В нем есть только строка: P   -  person nawfal    schedule 24.07.2014
comment
@nawfal нет, это строго набрано;)   -  person geekonaut    schedule 08.09.2015


Ответы (8)


В чем разница между языком со строгой типизацией и языком со статической типизацией?

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

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

Статический против динамического

Противоположностью статической типизации является "динамическая типизация", что означает, что

  1. Значения, используемые во время выполнения, классифицируются по типам.
  2. Существуют ограничения на использование таких значений.
  3. Когда эти ограничения нарушаются, нарушение регистрируется как ошибка (динамического) типа.

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

Сильный против слабого

Противоположностью «строго типизированного» является «слабо типизированный», что означает, что вы можете обойти систему типов. C, как известно, слабо типизирован, потому что любой тип указателя может быть преобразован в любой другой тип указателя простым преобразованием. Паскаль должен был быть строго типизированным, но из-за недосмотра в конструкции (записи непомеченных вариантов) в систему типов была образована лазейка, поэтому технически он не является типизированным. Примеры действительно строго типизированных языков включают CLU, Standard ML и Haskell. Фактически, стандартный ML претерпел несколько изменений, чтобы устранить лазейки в системе типов, которые были обнаружены после того, как язык получил широкое распространение.

Что здесь на самом деле происходит?

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

  • Любители часто объединяют их со «статикой» и «динамикой».

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

  • Профессионалы не могут прийти к единому мнению о том, что означают эти термины.

  • В целом вы вряд ли проинформируете или просветите свою аудиторию.

Печальная правда заключается в том, что когда дело доходит до систем типов, «сильные» и «слабые» не имеют универсально согласованного технического значения. Если вы хотите обсудить относительную силу систем типов, это Лучше обсудить, какие именно гарантии есть, а какие нет. Например, уместно задать следующий вопрос: «Гарантировано ли, что каждое значение данного типа (или класса) было создано путем вызова одного из конструкторов этого типа?» В C ответ - нет. В CLU, F # и Haskell - да. Что касается C ++, я не уверен, что хотел бы знать.

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

Одно подразумевает другое?

На педантичном уровне - нет, потому что слово «сильный» на самом деле ничего не значит. Но на практике люди почти всегда делают одно из двух:

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

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

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

person Norman Ramsey    schedule 23.04.2010
comment
@ Адам: Очевидно, недостаточно правильно, чтобы за него проголосовали :) Поскольку ответ Клетуса содержит так много заблуждений (хотя я вычеркнул худшие из них), я почувствовал себя обязанным изложить все словами из одного слога ... - person Norman Ramsey; 23.04.2010
comment
Что ж, я поддержал вас :) Даже слово «компиляция» не совсем однозначно для сегодняшних виртуальных машин, на которых работают динамические языки. Технически Java и C # компилируются дважды (JIT) и оба выполняют некоторый анализ типов. Такой язык, как Javascript, работающий в .NET vm, может быть более безопасным из-за виртуальной машины. - person Adam Gent; 25.04.2010
comment
Я так запуталась! Хорошо, дорогие великие гладиаторы арены, может ли такая бедная душа, как я, согласиться со следующим простым пониманием? 1. Статический: значения связаны с типом во время компиляции, а не во время выполнения. 2. Динамический: значения связаны с типом во время выполнения, поэтому тип значения может измениться во время выполнения ~, поэтому более подвержен проблемам, связанным с приведением типов. во время выполнения. 3. Сильный / слабый: забудьте об этом! Это не технические термины, а просто плохая номенклатура. Это зависит от того, о каком контексте идет речь. Могу ли я продолжать свою жизнь с этим простым пониманием? :( - person Saurabh Patil; 30.04.2014
comment
гарантировано ли, что каждое значение данного типа (или класса) было создано путем вызова одного из конструкторов этого типа? В C ответ - нет. Может ли кто-нибудь привести пример ситуации, когда это происходит в C? Я полагаю, это связано с приведением указателей к структурам? - person corazza; 31.08.2014
comment
Сильная и слабая типизация: такой классификации нет. - person Raúl; 24.02.2015
comment
@NormanRamsey Что касается C ++, я не уверен - я хотел бы знать: это то же самое, что и C. Можно легко разрушить систему типов, но, сделав это, в большинстве случаев вы получите неопределенное поведение. - person legends2k; 11.03.2015
comment
@NormanRamsey В своей редакции ответа Клетуса вы написали: [Я] не знал ни одного, в котором говорилось бы об изменении типа значений во время выполнения. Однако в разделе Программирование на Lua Роберто пишет, что Lua обеспечивает автоматическое преобразование чисел и строк во время выполнения. Кроме того, если язык допускает неявное преобразование, означает ли это, что он слабый, т.е. использует средство неявного преобразования (во время компиляции / выполнения), предоставляемое языком, означает подрыв системы типов? - person legends2k; 11.03.2015
comment
@SaurabhPatil В основном, да. Но обратите внимание, что даже в статически типизированном языке обычно используется полиморфизм, поэтому вам необязательно знать точный тип. Более важным моментом является то, что когда объект IStream, вы знаете, что он реализует этот интерфейс - вы не получите нарушения типа при вызове IStream.Read, даже если вы не знаете во время компиляции, является ли фактический тип FileStream или HttpStream или что-то еще. - person Luaan; 30.11.2016
comment
Сэр, я сомневаюсь, что строго типизированный означает, что если вы можете объединить строку и int без приведения, тогда это не строго типизировано. Этот ответ говорит именно об этом, но вы сказали, что C, как известно, слабо типизирован, потому что любой тип указателя может быть преобразован в любой другой тип указателя. просто путем кастинга. Пожалуйста, ответьте на него, если вы его видите, потому что я считаю, что вы никогда не отвечаете на комментарии к своему ответу. - person Suraj Jain; 08.01.2017
comment
@normanRamsey Elixir и erlang - сильная система динамических типов! :-) - person Jono; 05.04.2019

Это часто понимают неправильно, поэтому позвольте мне прояснить это.

Статический / динамический набор текста

Статическая типизация - это когда тип привязан к переменной. Типы проверяются во время компиляции.

Динамический тип - это когда тип привязан к значению. Типы проверяются во время выполнения.

Так, например, в 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 (что, возможно, удивительно, если вы с ним не знакомы) - нет.

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

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

Итак, чтобы ответить на ваш вопрос: другой способ взглянуть на это, который в основном верен, - это сказать, что статическая типизация - это безопасность типа во время компиляции, а строгая типизация - это безопасность типа во время выполнения.

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

Но важно понимать, что язык может быть статическим / сильным, статическим / слабым, динамическим / сильным или динамическим / слабым.

person cletus    schedule 22.04.2010
comment
Вместо того, чтобы говорить, что $ s является целым числом или строкой, было бы лучше, если бы вы сказали, что тип связан с abcd или 1234 не с переменной $ s. - person Srinivas Reddy Thatiparthy; 22.04.2010
comment
Отличный ответ с наглядными примерами. Однако я думаю, что это не полностью решает путаницу относительно того, ПОЧЕМУ люди спрашивают о сильном / статическом как о паре-близнецах. Например, формулировка OP о том, что статическая типизация ПОДРАЗУМЕВАЕТ строгую типизацию? Ваш ответ подчеркивает их независимость. Чтобы продолжить разъяснение того, почему сильное часто соединяется со статикой, предыдущий ответ Нормана Рэмси очень хорош: stackoverflow.com/questions/376611/ - person JasDev; 22.04.2010
comment
"abc" + 123 - это ошибка времени выполнения, а не ошибка компиляции в ruby. Если бы это была ошибка компиляции, рубин был бы статически типизирован. - person sepp2k; 22.04.2010
comment
Примеры слабой типизации нужно улучшить (см. Мой ответ), но в остальном форматирование будет приятным. - person Adam Gent; 23.04.2010
comment
По моему мнению, сильное и слабое типгин таково: Сильный: c + True = ошибка времени выполнения или ошибка времени компиляции. Слабый: c + True = b или d, потому что все обрабатывается как необработанные байты. Сильный: C #, Ruby, C ++ Слабый: Assembly, C (из-за неявных указателей void) - person Jonathan Allen; 23.04.2010
comment
Можно ли угонять такой ответ? Посередине есть странный абзац об исходном ответе, и я думаю, что первоначальное намерение автора было изменено во многих местах с редактированием. - person neonblitzer; 07.04.2020

Оба являются полюсами на двух разных осях:

  • строго типизированный или слабо типизированный
  • статически типизированный или динамически типизированный

Строго типизированный означает, что объект не будет автоматически преобразован из одного типа в другой. Слабая типизация - это наоборот: Perl может использовать строку типа "123" в числовом контексте, автоматически преобразовывая ее в int 123. Строго типизированный язык, такой как python, этого не сделает.

Статически типизированный означает, что компилятор определяет тип каждой переменной во время компиляции. Языки с динамической типизацией определяют типы переменных только во время выполнения.

person Daren Thomas    schedule 22.04.2010
comment
Я не согласен. Строго типизированный язык - это язык, который знает типы во время выполнения. Слабо типизированный язык - это язык, которому не нравится ассемблер. Ваш пример находится на третьей оси, неявные и явные преобразования. - person Jonathan Allen; 23.04.2010
comment
На самом деле нормально, я согласен, Джонатан, но вам не обязательно иметь типы, доступные во время выполнения, чтобы быть строго типизированными, если вы выполняете полный статический анализ и не разрешаете приведение типов. (см. мой отредактированный ответ). - person Adam Gent; 23.04.2010
comment
Python - это пример динамически типизированного и строго типизированного языка. - person MaRoBet; 18.02.2019

Строго типизированный означает, что существуют ограничения между преобразованиями между типами.

Статически типизированный означает, что типы не являются динамическими - вы не можете изменить тип переменной после ее создания.

person Svetlozar Angelov    schedule 22.04.2010
comment
Чтобы продемонстрировать это: в строго типизированном языке вы не можете сравнить 5 == 5 и получить истинное значение: строки не являются целыми числами. Если мне не изменяет память, большинство современных языков сценариев имеют строго динамическую типизацию. Tcl / Tk, однако, слабо типизирован - все можно рассматривать как строку. - person Little Bobby Tables; 22.04.2010
comment
Бобби, на языке со слабой типизацией 5 == 5 читается как 0x35 == 0x05. Или, другими словами, все обрабатывается как необработанные байты. - person Jonathan Allen; 23.04.2010
comment
Я не могу согласиться с вами обоими. Возьмите Lua; вы можете сравнить 5 == 5, и он вернет false, однако быстрое преобразование можно выполнить, набрав 5 + 0. - person RCIX; 27.04.2010

Принуждение данных не обязательно означает слабую типизацию, потому что иногда это синтаксический сахар:

В приведенном выше примере Java слабо типизирована из-за

String s = "abc" + 123;

Это не слабо типизированный пример, потому что он действительно делает:

String s = "abc" + new Integer(123).toString()

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

В этом отличие от C. C - один из лучших примеров слабо типизированных. Среда выполнения не знает, являются ли 4 байта целым числом, структурой, указателем или 4 символами.

Время выполнения языка действительно определяет, является ли он слабо типизированным, в противном случае это действительно справедливое мнение.

РЕДАКТИРОВАТЬ: После дальнейших размышлений это не обязательно верно, поскольку среда выполнения не должна иметь все типы, повторно введенные в систему времени выполнения, чтобы быть системой со строгой типизацией. Haskell и ML обладают настолько полным статическим анализом, что могут исключить информацию о типе из среды выполнения.

person Adam Gent    schedule 22.04.2010
comment
B, вероятно, лучший, хотя и немного менее известный пример. - person Tom Hawtin - tackline; 23.04.2010
comment
Javascript также довольно слабо типизирован, но из-за того, что их так мало, и потому что вы не можете создавать новые типы. - person Adam Gent; 23.04.2010

Ответ уже дан выше. Пытаемся провести различие между концепцией «сильная и недельная» и «статическая и динамическая».

Что такое сильно типизированный VS слабо типизированный?

Сильно типизированный: не будет автоматически преобразован из одного типа в другой

В Go или Python, как и в языках со строгой типизацией, "2" + 8 вызовут ошибку типа, потому что они не допускают "приведения типов".

Слабо (слабо) типизированный: будет автоматически преобразован из одного типа в другой. Слабо типизированные языки, такие как JavaScript или Perl, не выдадут ошибку, и в этом случае JavaScript выдаст «28», а perl - 10.

Пример Perl:

my $a = "2" + 8;
print $a,"\n";

Сохраните его в main.pl и запустите perl main.pl, и вы получите результат 10.

Что такое статический или динамический тип?

В программировании программист определяет статическую типизацию и динамическую типизацию по отношению к точке, в которой проверяются типы переменных. Языки со статической типизацией - это языки, в которых проверка типов выполняется во время компиляции, а языки с динамической типизацией - это языки, в которых проверка типов выполняется во время выполнения.

  • Статический: типы проверяются перед запуском
  • Динамический: типы проверяются на лету, во время выполнения

Что это значит?

В Go он проверяет набранный перед запуском (статическая проверка). Это означает, что он не только переводит и проверяет тип кода, который он выполняет, но он будет сканировать весь код, и ошибка типа будет выдана еще до того, как код будет запущен. Например,

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

Сохраните этот файл в main.go и запустите его, вы получите сообщение об ошибке компиляции.

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

Но этот случай не подходит для Python. Например, следующий блок кода будет выполняться для первого вызова foo (2) и завершится ошибкой для второго вызова foo (0). Это потому, что Python динамически типизирован, он только переводит и проверяет типы кода, в котором он выполняется. Блок else никогда не выполняется для foo (2), поэтому "2" + 8 даже не просматривается, а для вызова foo (0) он попытается выполнить этот блок и потерпит неудачу.

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

Вы увидите следующий вывод

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects
person Balkrishna    schedule 07.03.2019

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

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

person Joe Cannatti    schedule 22.04.2010

Сильная типизация, вероятно, означает, что переменные имеют четко определенный тип и что существуют строгие правила комбинирования переменных разных типов в выражениях. Например, если A - целое число, а B - число с плавающей запятой, то строгим правилом для A + B может быть то, что A приводится к типу с плавающей запятой, а результат возвращается как float. Если A - целое число, а B - строка, то строгим правилом может быть недопустимость A + B.

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

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

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

person High Performance Mark    schedule 22.04.2010