Баннер мобильный (3) Пройти тест

Типизация

Глоссарий

22 декабря 2023

Поделиться

Скопировано

Содержание

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

    Типизированные языки программирования — это практически все популярные современные языки: JavaScript, Python, C++, Java и многие другие. Во всех них есть типы и методы работы с ними. Но типизация в разных языках тоже разная.

    Например, в JavaScript одной переменной сначала можно присвоить строковое значение, а потом численное. А в C++ так нельзя и конкретный тип задается переменной навсегда.

    Для чего языкам программирования типизация

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

    Поэтому в языки программирования добавили возможность типизировать данные — разделять на типы и работать с каждым типом по-своему. Это помогло решить сразу несколько задач:

    • классифицировать данные;
    • сделать код более предсказуемым;
    • облегчить работу программиста;
    • увеличить читаемость кода;
    • упростить отладку.

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

    Какой бывает типизация

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

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

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

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

    Примеры языков с сильной типизацией: Python, Java, C#.

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

    Один из известнейших примеров языка с нестрогой типизацией
    Один из известнейших примеров языка с нестрогой типизацией — JavaScript. Про своеобразное поведение типов в этом языке ходит множество шуток. Например, на картинке — разные варианты сложения 2 и 2. Источник

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

    • Статическая типизация — это определение типа при компиляции. Это значит, что неправильную работу с типами программа «увидит» еще до того, как запустится. А еще тип каждой переменной задается раз и навсегда: нельзя переделать строковую переменную в численную. Статически типизированные языки программирования работают чуть быстрее, но код на них бывает сложнее писать.
    • Динамическая типизация — это определение типа при выполнении кода. То есть программа запускается, доходит до места, где объявляют какую-то переменную, и задает ей тип ровно в этот момент. В таких языках переменная может менять тип: в этой части кода в ней лежит число, а в другой — строка. Писать код на таких языках проще, но они обычно чуть менее эффективны, чем статические.

    Примеры статически типизированных языков: C/C++, Java, C#.

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

    Статическая и динамическая титипизация
    Часто строгий язык одновременно оказывается статическим, и наоборот. Но не всегда: например, Python строгий и динамический, а C++ нестрогий и статический. Источник

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

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

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

    Неявную типизацию еще называют латентной или утиной. Название «утиная типизация» возникло из английского выражения про уточку: «Если это выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, и есть утка». То есть неявно типизированные языки определяют тип по набору характерных признаков.

    Есть ли языки программирования без типов

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

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

    Большинство языков ассемблера — бестиповые. Кроме них, есть такие бестиповые языки, как Forth или BCPL. А еще есть эзотерические языки, созданные не для практических целей, а просто из развлечения или из любви к искусству. Они обычно очень запутанные и часто тоже бывают бестиповыми.

    код программы на эзотерическом языке Piet
    Это не схема здания, а код программы на эзотерическом языке Piet. Код на нём выглядит как цветные абстрактные картинки. Этот язык — тоже бестиповый. Источник

    Основные типы данных в программировании

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

    Целое число. Чаще всего называется Integer или int, что так и переводится — «целое». В некоторых языках несколько целочисленных типов разной длины, но для удобства разработки их чаще всего объединяют в один. В переменной этого типа хранится:

    • целое число;
    • положительное, отрицательное или 0;
    • диапазон зависит от языка.

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

    Дробное число. Этот тип может называться по-разному: float, flow и так далее. Это значит «число с плавающей запятой» — так называется представление дробного числа в виде десятичного. В переменной хранится:

    • дробное число;
    • положительное, отрицательное или 0.0;
    • число без дробной части обычно записывается как число с дробной частью 0, например 5.0.

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

    Строка. Строковой тип данных обычно называется string. В нем хранятся строки:

    • последовательность символов, обычно заключенная в кавычки;
    • в последовательности — буквы, цифры и разные знаки;
    • цифры в строке не воспринимаются как числа.

    В некоторых языках, например C#, еще есть тип char, где хранится только один символ. В других языках для этого тоже используется тип строки. Строки можно соединять друг с другом, разбивать на несколько подстрок, искать там вхождения, модифицировать и так далее.

    В нестрого типизированных языках строку бывает можно сложить с числом. Тогда язык автоматически попытается перевести один из типов в другой. Например, 2 + «2» в JavaScript будет равно 22.

    Булев тип. Обычно называется bool или boolean в честь английского математика Буля. Еще его называют логическим типом. Переменная этого типа может принимать только два значения: «правда» и «ложь». Вот как это выглядит:

    • два «классических» значения — true и false;
    • 0, пустая строка или пустая переменная автоматически равны false;
    • любое другое число или строка автоматически равны true.

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

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

    • набор значений может быть однотипным или разнотипным в зависимости от языка;
    • индексы, как правило, начинаются с 0, т. е. первый элемент будет считаться нулевым;
    • стандартно массив фиксирован по длине, но во многих языках есть динамические массивы — у них длина меняется.

    К элементам массива можно обращаться по индексам, перебирать их, хранить там наборы информации. А еще есть другие типы данных: список, словарь и так далее. Они похожи на массивы, но работают по другим правилам.

    Функция. Внутри переменной может лежать не только значение, но и инструкция — набор действий. Такие переменные называются функциями:

    • внутри хранится какой-то код;
    • можно вызвать функцию и исполнить этот код;
    • можно передать функции значение или получить от нее результат.

    В большинстве языков, чтобы вызвать функцию, нужно написать ее название и скобки после него: function_name(). Если надо передать функции какие-то данные, они как раз пишутся в скобках. А еще функцию можно переносить в другие переменные, тогда ее название пишется без скобок. Функция может возвращать результат своей работы, и этот результат можно записать в другую переменную.

    Объект. Очень обширный тип: строго говоря, в большинстве случаев к нему можно отнести и структуры данных, и функции, и любые сложные типы. Но классический объект имеет свою структуру. Внутри него хранятся;

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

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

    Объекты используют, чтобы описывать сложные структуры и приближать программные абстракции к человеческим понятиям. Этот тип — основа объектно-ориентированного программирования, но используется не только в нём.

    Что такое null, undefined и NaN

    У переменных в языках программирования бывают значения, которые нельзя отнести ни к одному из типов: NaN, null, undefined. Они не содержат в себе никаких значащих данных, говорят или об ошибке, или об отсутствии значения. Поговорим, чем отличаются null, undefined и NaN и что это вообще такое.

    • NaN — это Not a Number, «нечисло». Это значение-ошибка, которое появляется, если математическая операция выдала неопределенный либо некорректный результат. Например, кто-то попытался взять квадратный корень из строки и получил нечто нечитаемое. Это и есть NaN, значение, которое не равно ничему, даже самому себе;
    • undefined — это «неопределенное» значение. Его по умолчанию принимает переменная, в которую ничего не «положили». По сути, это запись «значения не существует»;
    • null — это «нулевое» значение. Не ноль, потому что ноль тоже что-то значит, а именно значение, ведущее «в никуда». Разница между null и undefined в том, что у undefined значения не существует в принципе. А у null оно есть и означает «пустота».

    Обычно говорят, что undefined означает «значения нет по ошибке». А null значит «значения нет намеренно».

    Можно ли перевести один тип в другой

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

    • Обычно можно перевести значение переменной отдельно от нее самой. Например, взять переменную one, в которой лежит число 1, перевести это 1 в строку «1» и записать в другую переменную. В переменной one останется лежать 1, а строковое значение запишется куда-то еще.
    • В языках с динамической типизацией можно изменить и тип самой переменной. В ту же самую переменную one можно записать сперва 1, а потом «1».
    • А еще иногда типы приводятся автоматически. Это обычно происходит в языках с нестрогой типизацией. Разработчик пытается, скажем, соединить строку и число — интерпретатор языка сам приводит значения к единому типу.

    Для перевода типов есть специальные команды и операторы. Например, в JavaScript можно поставить перед именем переменной плюс без пробела, чтобы ее значение в конкретном случае считалось как число: +переменная. При этом сама переменная не изменится.

    Какая типизация лучше

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

    • строгие языки более формализованные и предсказуемые, но ограничивают разработчика. Нестрогие гибче, но могут преподнести сюрпризы, не всегда приятные;
    • статические языки часто эффективнее и быстрее, динамические — удобнее и легче в использовании;
    • явно типизированные языки заставляют больше писать, зато код получается нагляднее. Неявная типизация лаконичнее, но с непривычки можно запутаться;
    • наконец, языки без типа очень сложные, зато позволяют работать с железом практически напрямую и не сталкиваться с ограничениями по типам вообще.

    Поделиться

    Скопировано

    0 комментариев

    Комментарии