Что такое Type-safe? - PullRequest
       92

Что такое Type-safe?

Ответы [ 12 ]

223 голосов
/ 04 ноября 2008

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

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

// 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 # поддерживает языковую функцию, называемую covariance , это в основном означает, что вы можете заменить базовый тип дочерним типом и не вызвать ошибку, например:

 public class Foo : Bar
 {
 }

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

 void DoSomething(Bar myBar)

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

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

void DoSomething(Foo myFoo)

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

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

44 голосов
/ 06 августа 2014

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

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

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

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

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

26 голосов
/ 04 ноября 2008

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

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

21 голосов
/ 09 января 2018

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

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

Память **

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

Визуально:

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

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

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

int >> char:

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

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

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

Тип данных

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

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

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

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

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

... Конечно, банковские программы используют гораздо большие типы данных. ;) LOL!

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

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

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

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

9 голосов
/ 31 июля 2015

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

  1. Вы не можете читать из неинициализированных переменных
  2. Вы не можете индексировать массивы за их пределами
  3. Вы не можете выполнять броски без проверки типа
8 голосов
/ 04 ноября 2008

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

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

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

 void foo(int arg)

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

  // call foo
  foo("hello world")

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

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

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

4 голосов
/ 15 января 2014

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

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

Теперь для длинного текста.

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

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

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

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

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

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

enter image description here

4 голосов
/ 04 ноября 2008

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

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

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

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

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

2 голосов
/ 27 октября 2011

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

2 голосов
/ 04 ноября 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 ... посмотрим).

...