Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 12.doc
Скачиваний:
10
Добавлен:
20.05.2015
Размер:
100.35 Кб
Скачать

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

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

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

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

type

indextype = 1. .100; {ограниченный тип}

var

count: integer;

index : indextype;

Если бы в Pascal использовалась совместимость имен типов, то переменные count и index не были бы совместимы.

Совместимость структур типов более гибка, но сложнее реализуется. При определении совместимости имен типов сравниваются только имена двух типов, а при использовании совместимости структур типов – структуры двух типов. Выполнить второе сравнение не всегда лег­ко. (Рассмотрите, например, структуру данных, ссылающуюся на собственный тип – связный список.) При этом могут возникать дополнительные вопросы. Являются ли, например, два структурных типа совместимыми, если они имеют одинаковую структуру, но разные имена полей? Совместимы ли два одномерных масси­ва в программе на языке Pascal или Ada, если они содержат элементы одного типа, но различаются областью значений индекса: 0..10 и 1..11?

Еще одной трудностью, связанной с совместимостью структур типов, является то, что она не признает различий между типами, имеющими одинаковую структуру. Рассмотрим следующее объявление, которое могло бы появиться в программе на языке Pascal:

type

celsius = real;

fahrenheit = real;

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

В исходном определении языка Pascal явно не устанавливается, когда должна использоваться совместимость структур типов, а когда – совместимость их имен. Это вредно для мобильности программ, поскольку программа, корректная в одной системе реализации языка, может оказаться некорректной в другой. Стандарт язы­ка Pascal, созданный Международной организацией по стандартизации, явно устанавливает правила совместимости типов для данного языка, частично – по имени, частично – по структуре. В большинстве случаев используется структура, а имя типа приме­няется для формальных параметров и в некоторых других ситуациях. Рассмотрим, на­пример, следующие объявления:

type

typel = array [1..10] of integer;

type2 = array [1..10] of integer;

type3 = type2;

В этом примере типы type1 и type2 несовместимы, что свидетельствует об интерпретации совместимости имен типов. Однако тип type2 совместим с типом type3, из чего можно заключить, что эквивалентность имен типов не трактуется строго. Такая форма совместимости иногда называется эквивалентностью объявлений, поскольку при определении типа с помощью имени другого ти­па оба они являются совместимыми, несмотря на то, что они несовместимы по именам типов.

В языке Ada применяется совместимость имен типов, но при этом имеются две кон­струкции – подтипы и производные типы, которые позволяют устранить возни­кающие проблемы. Производным называется новый тип, основанный на некотором ранее определенном типе, с которым он несовместим, несмот­ря на то, что они имеют идентичную структуру. Производные типы наследуют все свой­ства родительских типов. Рассмотрим следующий пример:

type celsius is new FLOAT;

type fahrenheit is new FLOAT;

Переменные типов celsius и fahrenheit несовместимы, хотя и имеют идентичную структуру. Более того, переменные этих типов несовместимы ни с каким другим типом чисел с плавающей точкой. Исключением из правила являются только литеральные константы. Литеральная константа, например, 3.0 имеет тип универсальных действительных чисел и совместима с любым типом чисел с плавающей точкой. Производные типы также могут содержать огра­ничения диапазона родительского типа, наследуя при этом все его операции.

Подтип в языке Ada – версия существующего типа с, возможно, ограничен­ным диапазоном. Подтип совместим с породившим его типом. Рассмотрим следующее объявление:

subtype SMALL_TYPE is INTEGER range 0..99;

Переменные, имеющие тип SMALL_TYPE, совместимы с переменными типа INTEGER.

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

В языке C применяется структурная эквивалентность для всех типов, за исключением структур (записей) и объединений, для которых используется эквивалентность объявлений. Правда, если две структуры или объединения определяются в двух различ­ных файлах, то используется эквивалентность структур типов.

В языке C++ используется эквивалентность имен типов. При этом отметим, что оператор typedef языков C и C++ не вводит новый тип. Он просто определяет новое имя для уже сущест­вующего типа.

Во многих языках переменные могут объявляться без использования имен типа, при этом соз­даются безымянные типы. Рассмотрим следующий пример из языка Ada:

A : array (1..10) of INTEGER;

В этом случае переменная A имеет безымянный, но неоднозначно определенный, тип. После объявления

В : array (1..10) of INTEGER;

переменные A и B будут принадлежать к безымянным, различным и несовместимым типам, хотя они имеют идентичную структуру. Множественное объявление

С, D : array (1..10) of INTEGER;

создаст два безымянных типа: один для переменной C, другой – для переменной D, не­совместимых между собой. Фактически эти объявления можно рассматривать как сле­дующие два объявления:

С : array (1..10) of INTEGER;

D : array (1..10) of INTEGER;

Однако в объявлении

type LIST__10 is array (1..10) of INTEGER;

C, D : LIST_10;

переменные C и D будут совместимыми.

Очевидно, что в языках, не позволяющих пользователям определять и называть типы, например FORTRAN и COBOL, эквивалентность имен применяться не может.

Возникновение таких объектно-ориентированных языков как C++, Java, C# подняло вопрос о новой концепции совместимости типов – совместимости объектов и ее связи с иерархией наследования.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]