Перейти к содержанию

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

Немаловажной особенностью типизации является понятие совместимости типов.

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

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

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

Номинативная типизация

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

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

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

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

Структурная типизация

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

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

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

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

Утиная типизация

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

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

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

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

Итоги

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