Что такое типобезопасный?

Что означает "типобезопасный"?




Ответы (12)


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

Несколько простых примеров:

// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";

Это также относится к аргументам метода, поскольку вы передаете им явные типы:

int AddTwoNumbers(int a, int b)
{
    return a + b;
}

Если бы я попытался вызвать это, используя:

int Sum = AddTwoNumbers(5, "5");

Компилятор выдаст ошибку, потому что я передаю строку («5»), и он ожидает целое число.

На слабо типизированном языке, таком как javascript, я могу делать следующее:

function AddTwoNumbers(a, b)
{
    return a + b;
}

если я назову это так:

Sum = AddTwoNumbers(5, "5");

Javascript автоматически преобразует 5 в строку и возвращает «55». Это связано с тем, что javascript использует знак + для конкатенации строк. Чтобы сделать его типизированным, вам нужно будет сделать что-то вроде:

function AddTwoNumbers(a, b)
{
    return Number(a) + Number(b);
}

Или, возможно:

function AddOnlyTwoNumbers(a, b)
{
    if (isNaN(a) || isNaN(b))
        return false;
    return Number(a) + Number(b);
}

если я назову это так:

Sum = AddTwoNumbers(5, " dogs");

Javascript автоматически преобразует 5 в строку и добавляет их, чтобы вернуть «5 собак».

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

Хотя это удобно, оно открывает вам множество ошибок, которые можно легко пропустить и выявить только при тестировании работающей программы. Лично я предпочитаю, чтобы мой компилятор сообщал мне, сделал ли я эту ошибку.

А теперь вернемся к C # ...

C # поддерживает языковую функцию под названием ковариация, это в основном означает, что вы может заменять дочерний тип базовым типом и не вызывать ошибки, например:

 public class Foo : Bar
 {
 }

Здесь я создал новый класс (Foo), который является подклассом Bar. Теперь я могу создать метод:

 void DoSomething(Bar myBar)

И вызовите его, используя в качестве аргумента либо Foo, либо Bar, оба будут работать без ошибок. Это работает, потому что C # знает, что любой дочерний класс Bar будет реализовывать интерфейс Bar.

Однако вы не можете сделать обратное:

void DoSomething(Foo myFoo)

В этой ситуации я не могу передать Bar этому методу, потому что компилятор не знает, что Bar реализует интерфейс Foo. Это связано с тем, что дочерний класс может (и обычно будет) сильно отличаться от родительского класса.

Конечно, теперь я ушел далеко за пределы исходного вопроса, но это все, что нужно знать :)

person FlySwat    schedule 04.11.2008
comment
Я считаю, что это неверный ответ: безопасность типов не обязательно обеспечивается во время компиляции. Я понимаю, что Scheme, например, считается типобезопасным, но проверяется динамически (безопасность типов обеспечивается во время выполнения). Это в основном перефразирование введения Бенджамина К. Пирса в «Типы и языки программирования». - person Nicolas Rinaudo; 02.02.2014
comment
То, что вы описываете, называется полиморфизмом, а не ковариацией. Ковариация используется в дженериках. - person IS4; 16.04.2015
comment
@NicolasRinaudo отмечает, что разрыв между динамическими и статическими языками стирается динамической компиляцией и прекомпиляцией для интерпретируемых языков, а также отражением в скомпилированных языках. Отражение позволяет, например, печатать утку во время выполнения, поэтому скомпилированный язык может сказать: «Эй, у него есть метод Quack ()», я вызову его и посмотрю, что произойдет. Паскальоподобные языки также часто имеют (необязательную) проверку переполнения во время выполнения, что приводит к тому, что ошибки компилятора, возникающие во время выполнения, не могут поместиться в целое число, указанное в 8-битном месте назначения {core dump}. - person Code Abominator; 24.05.2017
comment
Ваш пример ссылается на концепцию, называемую строго типизированной, что не то же самое, что и безопасность типов. Безопасность типов - это когда язык может обнаруживать ошибки типа во время выполнения или компиляции. Например, Python слабо типизирован и безопасен по типу. Этот ответ следует отметить, поскольку он вводит в заблуждение. - person dantebarba; 18.02.2019

Типобезопасность не следует путать со статической / динамической типизацией или строгой / слабой типизацией.

Типобезопасный язык - это язык, в котором единственные операции, которые можно выполнять с данными, - это те, которые поддерживаются типом данных. То есть, если ваши данные относятся к типу X и X не поддерживают операцию y, то язык не позволит вам выполнить y(X).

Это определение не устанавливает правил для , когда установлен этот флажок. Это может быть во время компиляции (статическая типизация) или во время выполнения (динамическая типизация), обычно через исключения. Это может быть и то, и другое: некоторые языки со статической типизацией позволяют преобразовывать данные из одного типа в другой, и достоверность приведений должна проверяться во время выполнения (представьте, что вы пытаетесь преобразовать Object в Consumer - компилятор не имеет возможности узнать, приемлемо это или нет).

Типовая безопасность не обязательно означает строго типизированный - некоторые языки, как известно, слабо типизированы, но все же возможно типобезопасны. Возьмем, к примеру, Javascript: его система типов настолько слабая, насколько это возможно, но все же строго определена. Он позволяет автоматически преобразовывать данные (например, строки в целые числа), но в рамках четко определенных правил. Насколько мне известно, нет случая, когда программа Javascript будет вести себя неопределенным образом, и если вы достаточно умны (а я нет), вы сможете предсказать, что произойдет при чтении кода Javascript.

Примером языка программирования с небезопасным типом является C: чтение / запись значения массива за пределами массива имеет неопределенное поведение по спецификации. Что произойдет, предсказать невозможно. C - это язык, который имеет систему типов, но не является типобезопасным.

person Nicolas Rinaudo    schedule 06.08.2014
comment
каковы еще примеры языков с небезопасным типом? Что вы имеете в виду, написав значение массива за пределами его границ, по спецификации имеет неопределенное поведение. Что произойдет, предсказать невозможно. Как и Javascript, он вернет undefined, верно? Или действительно все может случиться. Вы можете привести пример этого? - person ARK; 15.02.2018
comment
@AkshayrajKore конечно. Массивы - это указатели памяти, поэтому, записывая данные за пределы, вы можете перезаписать данные другой программы - которая ничего не может сделать, приведет к сбою программы или ее стиранию на жестком диске - она ​​не определена и зависит от того, кто читает этот бит памяти и как он отреагирует на это. - person Nicolas Rinaudo; 22.02.2018
comment
@Nicolas Rinaudo Это неверно. Вы должны прочитать о виртуальной памяти. Каждый процесс имеет собственное виртуальное адресное пространство, поэтому процесс не может перезаписать данные другой программы таким образом. - person ilstam; 08.07.2018
comment
Вы правы - это должно было быть прочитано вы могли перезаписывать другую часть памяти вашей программы - вплоть до самой программы включительно? - person Nicolas Rinaudo; 08.07.2018
comment
@NicolasRinaudo Сегмент кода программы отображается в виртуальном адресном пространстве только для чтения. Поэтому, если вы попытаетесь написать в него, это вызовет ошибку сегментации и ваша программа выйдет из строя. Также, если вы попытались записать в неотображенную память, это вызвало бы сбой страницы и снова сбой. Однако, если вам не повезло, вы можете просто перезаписать данные из стека или кучи процесса (например, других переменных или прочего). В этом случае вы, вероятно, не сразу рухнете, что еще хуже, потому что вы не заметите ошибку до (надеюсь) позже! - person ilstam; 13.07.2018
comment
Отличный ответ. Чтобы добавить, Python - еще один хорошо известный пример языка с динамической типизацией. - person dantebarba; 18.02.2019

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

Есть 2 основных вопроса, связанных с безопасностью типов. Память ** и тип данных (с соответствующими операциями).

Объем памяти**

Для char обычно требуется 1 байт на символ или 8 бит (в зависимости от языка, Java и C # хранят символы Unicode, для которых требуется 16 бит). int требует 4 байта или 32 бита (обычно).

Визуально:

char: |-|-|-|-|-|-|-|-|

int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

Типобезопасный язык не позволяет вставлять int в char во время времени выполнения (это должно вызывать какое-то преобразование класса или исключение нехватки памяти). Однако в языке с небезопасным типом вы бы перезаписали существующие данные еще в 3 соседних байтах памяти.

int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

В приведенном выше случае 3 байта справа перезаписываются, поэтому любые указатели на эту память (скажем, 3 последовательных символа), которые ожидают получения предсказуемого значения char, теперь будут иметь мусор. Это вызывает undefined поведение в вашей программе (или, что еще хуже, в других программах, в зависимости от того, как ОС выделяет память - в наши дни это маловероятно).

** Хотя технически эта первая проблема не связана с типом данных, типобезопасные языки решают ее по сути и визуально описывают проблему для тех, кто не знает, как «выглядит» выделение памяти.

Тип данных

Более тонкая и прямая проблема типа заключается в том, что два типа данных используют одно и то же выделение памяти. Возьмите int против беззнакового int. Оба 32 бита. (Так же легко могут быть char [4] и int, но более распространенная проблема - uint vs. int).

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

Язык небезопасного типа позволяет программисту ссылаться на правильно выделенный диапазон из 32 бит, но когда значение беззнакового int считывается в пространство int (или наоборот), мы снова имеем поведение undefined. Представьте себе проблемы, которые это может вызвать в банковской программе:

«Чувак! Я овердрафтил 30 долларов, и теперь у меня осталось 65 506 долларов !!»

... Конечно, банковские программы используют гораздо большие типы данных. ;) РЖУ НЕ МОГУ!

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

Скорость против безопасности

Большинству программистов сегодня не нужно беспокоиться о таких вещах, если они не используют что-то вроде C или C ++. Оба этих языка позволяют программистам легко нарушать безопасность типов во время выполнения (прямое обращение к памяти), несмотря на все усилия компиляторов по минимизации риска. ОДНАКО, это не так уж и плохо.

Одна из причин, по которой эти языки настолько быстры в вычислениях, заключается в том, что они не обременены проверкой совместимости типов во время выполнения операций, таких как, например, Java. Они предполагают, что разработчик - хорошее рациональное существо, которое не будет складывать вместе строку и int, и за это разработчик вознаграждается скоростью / эффективностью.

person Gr3go    schedule 09.01.2018
comment
Верно, что обеспечение безопасности типов накладывает ограничения на скорость. Но действительно важно, чтобы была обеспечена безопасность типов, учитывая, что код C / C ++ более уязвим для атак BufferOverflow и других связанных атак. Угрозы таких атак уменьшаются за счет обеспечения безопасности типов. - person Prateek93a; 11.03.2021

Многие ответы здесь объединяют безопасность типов со статической и динамической типизацией. Язык с динамической типизацией (например, smalltalk) также может быть типобезопасным.

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

person ididak    schedule 04.11.2008
comment
Подождите, в вашем определении типобезопасности нет единственного слова type: D if no operation leads to undefined behavior. - person VasiliNovikov; 02.09.2014
comment
Также я бы не согласился с таким определением. Я думаю, что безопасность типов означает в точности 1. существование типов 2. знание о них компилятору и, конечно же, соответствующие проверки. - person VasiliNovikov; 02.09.2014

Типобезопасный язык программирования означает следующее:

  1. Вы не можете читать из неинициализированных переменных
  2. Вы не можете индексировать массивы за их пределами
  3. Вы не можете выполнять приведение типов без отметки
person Kekule    schedule 31.07.2015

Объяснение, полученное по специальности "гуманитарные науки", а не по специальности:

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

Например, в C # я определяю функцию как:

 void foo(int arg)

Тогда компилятор остановит меня от этого:

  // call foo
  foo("hello world")

На других языках компилятор меня не остановит (или компилятора нет ...), поэтому строка будет передана в логику, и тогда, вероятно, произойдет что-то плохое.

Типобезопасные языки пытаются уловить больше «во время компиляции».

С другой стороны, с типобезопасными языками, когда у вас есть строка типа "123" и вы хотите работать с ней как с int, вам нужно написать больше кода для преобразования строки в int, или когда у вас есть int например, 123 и хотите использовать его в сообщении типа «Ответ 123», вам нужно написать больше кода для преобразования / преобразования его в строку.

person Corey Trager    schedule 04.11.2008
comment
Специалист по гуманитарным наукам сказал бы объяснение :) Вы также объединяете статическую типизацию и динамическую типизацию. - person ididak; 04.11.2008
comment
Гуманитарные специальности, а не специальность. - person Corey Trager; 06.11.2008

Чтобы лучше понять, посмотрите видео ниже, в котором демонстрируется код на безопасном языке (C #), а НЕ на безопасном языке (javascript).

http://www.youtube.com/watch?v=Rlw_njQhkxw

Теперь о длинном тексте.

Безопасность типов означает предотвращение ошибок типов. Ошибка типа возникает, когда тип данных одного типа НЕИЗВЕСТНО присваивается другому типу и мы получаем нежелательные результаты.

Например, JavaScript НЕ является типобезопасным языком. В приведенном ниже коде «num» - это числовая переменная, а «str» - это строка. Javascript позволяет мне делать «num + str», теперь УГАДАЙ, будет ли он выполнять арифметические операции или конкатенацию.

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

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

<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays  “55”
</script>

C # - это типобезопасный язык. Он не позволяет назначать один тип данных другому типу данных. В приведенном ниже коде нельзя использовать оператор «+» для разных типов данных.

введите описание изображения здесь

person Shivprasad Koirala    schedule 15.01.2014

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

На практике это означает, что 7 (целочисленный тип) отличается от «7» (заключенный в кавычки символ строкового типа).

PHP, Javascript и другие языки динамических сценариев обычно имеют слабую типизацию, так как они преобразуют (строку) «7» в (целое) 7, если вы попытаетесь добавить «7» + 3, хотя иногда вам приходится это делать. явно (а Javascript использует символ «+» для конкатенации).

C / C ++ / Java этого не поймет или вместо этого объединит результат в "73". Типовая безопасность предотвращает эти типы ошибок в коде, делая требование типа явным.

Безопасность типов очень полезна. Решением вышеупомянутого «7» + 3 было бы ввести cast (int) «7» + 3 (равно 10).

person Jared Farrish    schedule 04.11.2008

Попробуйте это объяснение на ...

TypeSafe означает, что переменные статически проверяются на предмет соответствующего присвоения во время компиляции. Например, введите строку или целое число. Эти два разных типа данных не могут быть перекрестно назначены (т. Е. Вы не можете присвоить целое число строке или присвоить строку целому числу).

Для нетипизированного поведения учтите следующее:

object x = 89;
int y;

если вы попытаетесь сделать это:

y = x;

компилятор выдает ошибку, в которой говорится, что он не может преобразовать System.Object в Integer. Вам нужно сделать это явно. Один из способов:

y = Convert.ToInt32( x );

Приведенное выше назначение небезопасно. Типизированное присвоение - это когда типы могут быть напрямую назначены друг другу.

В ASP.NET изобилуют нетипизированные коллекции (например, коллекции приложений, сеансов и состояний просмотра). Хорошая новость об этих коллекциях заключается в том, что (сводя к минимуму необходимость управления несколькими состояниями сервера) вы можете поместить практически любой тип данных в любую из трех коллекций. Плохая новость: поскольку эти коллекции не являются типизированными, вам нужно будет соответствующим образом привести значения, когда вы вернете их обратно.

Например:

Session[ "x" ] = 34;

работает отлично. Но чтобы вернуть целочисленное значение, вам необходимо:

int i = Convert.ToInt32( Session[ "x" ] );

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

C # - это типизированный язык, но следите за статьями о C # 4.0; появляются интересные динамические возможности (хорошо ли, что C #, по сути, получает Option Strict: Off ... посмотрим).

person rp.    schedule 04.11.2008
comment
Лично я ненавижу нотацию Convert.To, почему бы вам просто не использовать безопасное приведение? Это единственный меньший вызов функции в стеке вызовов. - person FlySwat; 04.11.2008

Концепция:

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

  1. нет неправильного типа данных, например невозможно сохранить или инициализировать переменную строкового типа с целым числом
  2. Индексы за пределами границ недоступны
  3. Разрешить только определенную ячейку памяти

так что все дело в безопасности типов вашего хранилища с точки зрения переменных.

person azizsagi    schedule 28.11.2018

Type-Safe - это код, который обращается только к тем ячейкам памяти, к которым ему разрешен доступ, и только четко определенными допустимыми способами. Типобезопасный код не может выполнить операцию с объектом, недопустимым для этого объекта. Компиляторы языков C # и VB.NET всегда создают типобезопасный код, который проверяется на типобезопасность во время JIT-компиляции.

person Jonuz    schedule 27.10.2011
comment
Вы имеете в виду безопасность памяти? - person golopot; 20.11.2017

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

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

Многие языки с типобезопасностью создают иллюзию «безопасности типов», настаивая на строгом определении типов для переменных и позволяя присваивать переменной только значения одного и того же «типа». У этого подхода есть пара проблем. Например, в программе может быть переменная yearOfBirth, указывающая год рождения человека, и возникает соблазн преобразовать ее в короткое целое число. Однако это не короткое целое число. В этом году это число меньше 2009 и больше -10000. Однако этот набор увеличивается на 1 каждый год по мере выполнения программы. Сделать это «коротким int» недостаточно. Чтобы сделать эту переменную типобезопасной, необходима функция проверки во время выполнения, которая гарантирует, что число всегда будет больше -10000 и меньше, чем в следующем календарном году. Не существует компилятора, который мог бы применять такие критерии, потому что эти критерии всегда являются уникальными характеристиками предметной области.

Языки, использующие динамическую типизацию (или утиную типизацию, или манифестную типизацию), такие как Perl, Python, Ruby, SQLite и Lua, не имеют понятия типизированных переменных. Это вынуждает программиста написать процедуру проверки во время выполнения для каждой переменной, чтобы убедиться, что она верна, или выдержать последствия необъяснимых исключений во время выполнения. По моему опыту, программисты на статически типизированных языках, таких как C, C ++, Java и C #, часто убаюкивают себя, думая, что статически определенные типы - это все, что им нужно сделать, чтобы получить преимущества безопасности типов. Это просто неверно для многих полезных компьютерных программ, и трудно предсказать, верно ли это для какой-либо конкретной компьютерной программы.

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

person Jay Godse    schedule 04.11.2008
comment
Переменные Python типизированы (на самом деле строго типизированы). Попробуйте сделать это, например: str + 1. Вы получите сообщение об ошибке. Однако типы проверяются во время выполнения, а не во время компиляции. - person mipadi; 04.11.2008