система_типов

Система типов

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

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

Примеры статически типизированных языков: C, C++, Pascal, BASIC, Java, C#, D, Go, Rust, Fortran, Haskell, ML.

Примеры динамически типизированных языков: Perl, Python, Ruby, PHP, JavaScript, Smalltalk.

Примитивный или простой тип является встроенным типом языка. К таким типам относят, в первую очередь, алгебраические типы: целочисленный (integer), вещественный (real), символьный (char), логический (boolean). Характерной особенностью алгебраических типов является фиксированная длина - чаще всего 8, 16, 32 и 64 бит. В некоторых языках строковой тип (string) также является примитивным (в C-подобных языках строковой тип является разновидностью массива). Также некоторые языки расширяют этот набор более сложными математическими объектами - такими как вектор, матрица, комплексное число и т.д. Примитивным типом также является указатель, использующийся для хранения адресов ячеек памяти.

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

  • Массив (array) - это упорядоченный набор однотипных значений (элементов), доступ к которым осуществляется по целочисленному индексу
  • Структура (structure) - упорядоченный набор разнотипных значений (полей), доступ к которым осуществляется по именам.

В некоторых языках также поддерживаются следующие составные типы:

  • Класс (class) - образец для создания объектов. Подобен структуре, но, помимо полей, может содержать методы - функции, сопоставленные с объектом. Классы поддерживают полиморфизм и наследование
  • Интерфейс (interface) - разновидность контракта, гарантирующая доступ к определенным методам без привязки к конкретному классу. Переменные интерфейсного типа могут хранить любые объекты, реализующие этот интерфейс
  • Перечисление (enumeration) - тип, принимающий значение из определенного пользователем фиксированного множества именованных констант. Называется перечислением, так как поддерживает автоматическое сопоставление имен уникальным числовым константам, ранжированным в порядке увеличения - то есть, перечисляет константы
  • Ассоциативный массив, словарь или хэш-таблица - структура данных, сопоставляющая значения одного типа значениям другого типа.
  • Множество - неупорядоченный набор однотипных значений, каждый элемент которого уникален.

Примитивные типы имеют ограниченный диапазон возможных значений. Например, тип char обычно имеет длину 8 бит и, соответственно, имеет 256 возможных значений. Если попытаться преобразовать (привести) 32-битный целочисленный тип к типу char, произойдет потеря точности: верхние байты будут срезаны. Это считается небезопасным, так как может привести к трудноуловимым багам при бездумном использовании. Типизация языка называется сильной, если в нем приведение типов с потерей точности отсутствует в принципе, либо всегда осуществляется явно. В противоположность этому, языки со слабой типизацией допускают неявное приведение типов с потерей точности - например, при сохранении значения в переменную. Некоторые компиляторы при этом могут выводить предупреждение.

Примеры языков со слабой типизацией: C, C++.

Примеры языков с сильной типизацией: Java, C#, D, Rust, Pascal, Lisp, ML, Haskell.

В языке с сильной статической типизацией тип любого выражения может быть определен (выведен) семантическим анализатором на основе заданных правил совместимости типов. В некоторых языках это позволяет, например, опустить тип при объявлении переменной, если она инициализируется литералом или выражением. Вывод типов поддерживается в ML, Haskell, F#, D, C++11, Go, Rust, Dart, Scala, Vala, Swift.

Некоторые языки расширяют эту идею возможностью вычисления выражения во время компиляции (compile-time evaluation, CTE), если все входные данные выражения известны заранее. Эта возможность даже может включать выполнение функций, не имеющих побочных эффектов (compile-time function execution, CTFE). На момент написания статьи CTFE поддерживается в Lisp, D и C++14.

  • система_типов.txt
  • Последнее изменение: 2021/03/15 09:24
  • (внешнее изменение)