В чем разница между языком со строгой типизацией и языком со статической типизацией? - PullRequest
384 голосов
/ 22 апреля 2010

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

Ответы [ 8 ]

469 голосов
/ 23 апреля 2010

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

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

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

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

Противоположностью статически типизированного является «динамически типизированный», что означает, что

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

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

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

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

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

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

  • Любители часто связывают их со "статическим" и "динамическим".

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

  • Профессионалы не могут договориться о том, что именно означают термины.

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

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

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

Означает ли одно другое?

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

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

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

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

228 голосов
/ 22 апреля 2010

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

Статическая / динамическая печать

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

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

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

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

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

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

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

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

15 голосов
/ 22 апреля 2010

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

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

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

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

12 голосов
/ 22 апреля 2010

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

11 голосов
/ 22 апреля 2010

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

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

String s = "abc" + 123;

Не является типом со слабым типом, потому что это действительноrunning:

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

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

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

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

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

8 голосов
/ 22 апреля 2010

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

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

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

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

6 голосов
/ 22 апреля 2010

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

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

0 голосов
/ 08 марта 2019

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

Что такое строго типизированный 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.

Что такое статический тип VS и Dyamic?

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

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

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

В 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
...