среда, 22 февраля 2012 г.

Идентичность и совместимость типов данных

Перевод из справочной системы Delphi

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

  • Идентичность типов
  • Совместимость типов


Идентичность типов

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

type
  T1 = Integer;
  T2 = T1;
  T3 = Integer;
  T4 = T2;

T1, T2, T3, T4 и Integer связываются с одним и тем же типом. Для создания нового типа следует повторить слово type в объявлении. Например, объявление:

type TMyInteger = type Integer;

создает новый тип с именем TmyInteger, который не является типом, идентичным типу Integer. Конструкции языка, которые работают как имена типов, создают уникальный тип при каждом объявлении. То есть, объявления:

type
  TS1 = set of Char;
  TS2 = set of Char;
Создают два разных типа TS1 и TS2. Также как и объявления переменных
var
  S1: string[10];
  S2: string[10];

Создают две переменные различных типов. Чтобы создать переменные одного типа необходимо сделать объявление:

var S1, S2: string[10];
или:
type MyString = string[10];
var
    S1: MyString;
    S2: MyString;

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

Каждый тип совместим сам с собой. Два разных типа совместимы между собой, если они удовлетворяют хотя бы одному из нижеперечисленных условий:

  • Они оба относятся к дробным числам.
  • Они относятся к целым числам.
  • Один из типов является подмножеством второго.
  • Оба типа являются подмножествами третьего типа.
  • Оба типа являются множествами и их базовые типы совместимы.
  • Оба типа являются упакованными строками с одним и тем же количеством символов.
  • Один из типов – строковый, а другой – строка, упакованная строка или Char.
  • Один из типов – Variant, а другой – integer, real, string, character или Boolean.
  • Оба типа являются классами, ссылками на класс или интерфейсами, причем один тип унаследован от другого.
  • Один тип – PansiChar или PwideChar, а другой – массив символов с нулевым элементом вида array[0..n] of PAnsiChar или PWideChar.
  • Один тип – Pointer (нетипизированный указатель), а второй – любой указательный тип.
  • Оба типа являются типизированными указателями одного типа, при этом действует директива компилятора {$T+}.
  • Оба типа являются процедурными с одним и тем же типом результата, одинаковым количеством параметров с идентичными типами на соответствующих позициях.

Совместимость по присваиванию

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

  • T1 и T2 относятся к одному и тому же типу, при этом он не является файловым типом или структурированным типом, содержащим файл на любом из уровней.
  • T1 и T2 – это совместимые порядковые типы.
  • T1 и T2 – это дробные числовые типы.
  • T1 является дробным числовым типом, а T2 – целочисленный тип.
  • T1 – это PAnsiChar, PWideChar, PChar или любой строковый тип, а выражение – это строковая константа.
  • T1 и T2 оба являются строковыми типами.
  • T1 – это строковый тип, а T2 – это Char или упакованная строка.
  • T1 – это длинная строка, а T2 – это PAnsiChar, PWideChar или PChar.
  • T1 и T2 – совместимые упакованные строковые типы.
  • T1 и T2 – это совместимые подмножества.
  • T1 и T2 – это совместимые указательные типы.
  • T1 и T2 оба являются классами, ссылками на классы или интерфейсами, при этом T2 унаследован от T1.
  • T1 – это интерфейс, а T2 – это класс, реализующий T1.
  • T1 - это PAnsiChar или PWideChar, а T2 – это массив с нулевым элементом вида array[0..n] of Char (когда T1 это PAnsiChar) или of WideChar (когда T1 это PWideChar).
  • T1 и T2 – это совместимые процедурные типы. (Идентификатор функции или процедуры обрабатывается в определенных инструкциях присваивания как выражение процедурного типа. См. Процедурные типы в инструкциях и выражениях.)
  • T1 - это Variant, а T2 – это значение типа integer, real, string, символьный тип, Boolean, интерфейс или OleVariant.
  • T1 – это OleVariant, а T2 – это integer, real, string, character, Boolean, интерфейс или Variant.
  • T1 – это integer, real, string, character или Boolean, а T2 – это значение типа Variant или OleVariant.
  • T1 – относится к интерфейсным типам IUnknown или IDispatch, а T2 – это значение типа Variant или OleVariant. (Код типа варианта должен быть varEmpty, varUnknown или varDispatch, когда T1 – это IUnknown, и varEmpty или varDispatch, когда T1 – это IDispatch.)

  • Объявление типов

    Синтаксис объявления типов

    Объявление типа определяет идентификатор, ссылающийся на тип данных. Синтаксис объявления типа следующий:

    type newTypeName = type
    где newTypeName это допустимый идентификатор. Например, объявив следующий тип:
    type TMyString = string;
    вы можете следующее объявление переменной:
    var S: TMyString;

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

    type TValue = Real;
    var
      X: Real;
      Y: TValue;

    X и Y относятся к одному типу, после запуска приложения нет возможности отличить TValue от Real. Это обычно не имеет значения, но если вы определяете новый тип с целью использовать информацию о типе в режиме выполнения приложения, например, для связи редактора свойств со свойствами определенного типа – различие между разными названиями типов и разными типами становится важным. В этом случае следует использовать следующий синтаксис:

    type newTypeName = type KnownType
    Например, объявление:
    type TValue = type Real;

    заставляет компилятор создать новый, уникальный тип TValue. Для параметров, передаваемых по ссылке, формальные и фактические типы должны быть идентичными. Например:

    type
      TMyType = type Integer
    procedure p(var t:TMyType);
      begin
      end;
    
    procedure x;
    var
      m: TMyType;
      i: Integer;
    begin
      p(m); // Works
      p(i); 
      // Error! Types of formal and actual must be identical.
    end;
    
    Замечание: Это относится только к параметрам, передаваемым по ссылке, но не к параметрам-константам и не к параметрам, передваемым по значению.

    Комментариев нет:

    Отправить комментарий