Переменные типа ссылки Назад В начало Вперед

Синтаксис объявления переменной-ссылки (далее просто ссылки) следующий:

<ссылка> = <имя-ссылки> : <тип-ссылки> [ new | noAuto ];

<имя-ссылки> - имя переменной-ссылки.

<имя-ссылки> = <идентификатор>

<тип-ссылки> - тип переменной-ссылки определяется интерфейсом, на который переменная может ссылаться:

<тип-ссылки> = <vip-интерфейс>
  | <obj-интерфейс> [ (<vip-интерфейс-инициализации>) ]
  | objRef

<vip-интерфейс> - имя vip-интерфейса, ссылка на который может храниться в переменной.

<vip-интерфейс> = <идентификатор>

<obj-интерфейс> - имя obj-интерфейса, ссылка на который может храниться в переменной.

<obj-интерфейс> = <идентификатор>

<vip-интерфейс-инициализации> - автоматическая инициализация ссылки на obj-интерфейс значением ссылки на vip-интерфейс. Тот факт, что указанный vip-интерфейс реализует нужный obj-интерфейс проверяется во время компиляции. Если на момент исполнения vip-интерфейс не найден, то выдаётся ошибка.

<vip-интерфейс-инициализации> = <идентификатор>

objRef - абстрактная ссылка. Это ссылка на произвольный vip или obj-интерфейс. Ссылке такого типа можно присвоить ссылку произвольного типа, и наоборот (см. Пример 2).

new - переменная инициализируется ссылкой на индивидуальный экземпляр интерфейса. Индивидуальный экземпляр создается каждый раз, когда запрашивается ссылка такого рода. Для получения ссылок на индивидуальные экземпляры используются функции LoadVipInterface и LoadVipRef.

Если опция new не указана, то переменная инициализируется ссылкой на разделяемый vip-интерфейс. Разделяемый экземпляр всегда один (для данной среды исполнения), сколько бы ссылок на него не запрашивалось; ссылки на разделяемые экземпляры запрашиваются с помощью функций GetVipInterface и GetVipRef.

noAuto - выключить автоинициализацию. Такие переменные необходимо инициализировать самостоятельно.

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

Если не указана опция noAuto, то происходит автоматическая инициализация переменной. Автоматическая инициализация происходит в момент первого использования переменной (присвоения, приведения типа, вызова метода, использования в фактических параметрах функций и т.д.).

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

Выгрузка копии интерфейса и освобождение ссылки (деинициализация) выполняются функцией FreeVipInterface. С помощью функции NullVipRef можно проверить - инициализирована ли переменная типа ссылки.

Для всех переменных типа ссылки поддерживается автоматическое освобождение ссылки при выходе из области существования переменной. Автоматическое освобождение равносильно вызову функции FreeVipInterface.

Для всех экземпляров (и разделяемых, и индивидуальных) Vip-интерфейсов ведется подсчет количества активных ссылок. Счетчик ссылок увеличивается каждый раз, когда значение ссылки помещается в переменную. Счетчик ссылок уменьшается каждый раз, когда значение ссылки теряется - либо в результате присвоения другого значения ссылки, либо при выходе переменной из области существования, либо в результате явного освобождания ссылки с помощью функции FreeVipInterface.

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

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

При загрузке VIP-интерфейсов и вызове их методов могут возбуждаться следующие исключения:

Ограничения для переменной типа ссылки:

В интерфейсе, вызывающем методы внешнего интерфейса, необходимо описать переменную, являющуюся ссылкой на вызываемый интерфейс - объектный, либо VIP-интерфейс.

Если объявлена ссылка на VIP-интерфейс с прототипом, то с ее помощью можно использовать функции только первого объектного интерфейса, реализуемого данным VIP-интерфейса.

Для вызова методов внешнего интерфейса используется следующая конструкция:

<вызов-метода-внешнего-интерфейса> =
  <имя-ссылки>.<вызов-метода>

<имя-ссылки> - имя ссылки, задается при объявлении ссылки (см. выше).

<вызов-метода> - обычное обращение к методу:

<вызов-метода> =
  <имя-метода> [ (<список-фактических-параметров>) ]

Примеры

Пример 1. Переменные типа ссылки

В примере объявлены переменные:

var
  x : ISelectPodr;
  aMyIfc : MyInterface new;
  aIfc2  : MyInterface noAuto;
........

Пример 2. Переменная типа абстрактной ссылки

var ref1, ref2 : Vip1;
var oRef : objRef;
  ...
  oref := ref1;
  ref2 := oref;

Пример 3. Использование нулевой ссылки

var ref1 : vip1;
...
ref1.DoSomething(NullRef); // автоинициализация + вызов метода
ref1 := NullRef; 	 // освобождение ссылки
if (ref1 = NullRef)		// снова автоинициализация
  Message('Ok'); 	 // это сообщение никто не увидит ...

Пример 4.

//=========================================================
vipInterface VipInterface01;

//=========================================================
interface VipInterface01;
end.

//=========================================================
objInterface ObjInterface02;
 property pVI01: VipInterface01 read write;
end;

//=========================================================
vipInterface VipInterface02 implements ObjInterface02;

//=========================================================
interface VipInterface02;

var pTmp: VipInterface01;
var pRef: VipInterface01;

property pVI01: VipInterface01 absolute pTmp;

//---------------------------------------------------------
function CheckRef: boolean;
{
  result := NullVipRef(pRef);
}

//---------------------------------------------------------
function GetRef: VipInterface01;
{
  GetRef := pRef;
}

//---------------------------------------------------------
procedure Msg(s: string; b: boolean);
{
  Message(s + ' is' + String(If(b, '', ' not')) + ' null');
}

//---------------------------------------------------------
handleEvent

cmInit:
{
  var i: VipInterface01;
  var oi: ObjInterface02(VipInterface02);

  Msg('i', NullVipRef(i)); //сообщение: "i is null"
  Msg('i', i=NullRef);  //сообщение: "i is not null"
  Msg('i', NullVipRef(i)); //сообщение: "i is not null"

  Msg('Ref', CheckRef); 	 //сообщение: "Ref is null"
  Msg('Ref', NullVipRef(GetRef)); //сообщение: "Ref is not null"
  Msg('Ref', CheckRef); 	 //сообщение: "Ref is not null"

  Msg('pVI01', NullVipRef(pTmp));  //сообщение: "pVI01 is null"
//сообщение: "pVI01 is not null":
  Msg('pVI01', NullVipRef(ObjInterface02(self).pVI01));
  Msg('pVI01', NullVipRef(pTmp));  //сообщение: "pVI01 is not null"
}

end;

end.

Смотрите также

Функции вызова методов внешнего интерфейса.

События, связанные с использованием внешних интерфейсов

Версия

Начиная с версии 5.0 переменная типа ссылки на vip-интерфейс может быть описана как глобальная, а также в секциях .var и .fields в шаблонах форм.