Совместимость типов на основе вида типизации

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

Совместимость типов (Types Compatibility)

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

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

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

nominative types shared

Номинативная Типизация (nominative typing)

Номинативная типизация (nominative typing) устанавливает совместимость типов основываясь на идентификаторах типов (ссылках). Простыми словами, при проверке на совместимость компилятор проверяет иерархию типов на признаки наследования и реализацию интерфейсов. То есть, тип B будет совместим с типом A только тогда, когда он является его предком (extends). Кроме того, тип B будет совместим с интерфейсом IA только в том случае, если он или один из его предков реализует его явно (implements).

nominative types nominative principle

Как можно понять по изображению выше, при проверке на совместимость типа Bird с типом Animal компилятор обходит дерево в поисках наличия ссылки на тип Animal и обнаружив её, приходит к выводу, что типы совместимы. Тот же самый процесс требуется для установления совместимости типа Bird с типом интерфейса INameable. Полная картина совместимости изображена на диаграмме ниже.

Номинативная типизация присуща исключительно статически типизированным языкам.

К языкам с номинативной типизацией относятся Java, C# и другие.

Структурная Типизация (structural typing)

Структурная типизация — это принцип, определяющий совместимость типов основываясь не на иерархии наследования или явной реализации интерфейсов, а на их описании.

nominative types structural principle

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

nominative types structural compatible

Структурная типизация присуща исключительно языкам с явной типизацией (глава “Экскурс в типизацию - Сильная и слабая типизация”).

К языкам со структурной типизацией относятся TypeScript, Scala и им подобные.

Утиная Типизация (Duck typing)

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

Термин «Утиная типизация» произошёл от английского выражения duck test, который в оригинале звучит как - Если это выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, и есть утка.

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

К языкам с утиной типизацией относятся Python, JavaScript и другие.