понедельник, 20 октября 2014 г.

Об "опасностях" ARC и прочих "автоматов". Развиваем тему

Предыдущий пост был тут - Об "опасностях" ARC и прочих "автоматов". Пока коротко

Разовьём тему.

Пусть у нас есть "аналог" IStorage:

type
 ImyStorage = interface
  ...
  fuction Open(const aName: String): ImyStorage;
  ...
 end;//ImyStorage

-- И пусть спецификация работы с интерфейсом такова - если мы открыли "внутреннее хранилище", то мы не можем открыть его снова, если мы его не отпустили.

Приведу пример:

procedure ProcessStorage(const aRoot: ImyStorage);
var
 l_A1 : ImyStorage;
 l_A2 : ImyStorage;
begin
 l_A1 := aRoot.Open('A').Open('1');
 // - тут всё хорошо, тут всё открылось
 ...
 l_A2 := aRoot.Open('A').Open('2');
 // - тут всё плохо, тут НЕ ОТКРЫЛОСЬ
 //   ПОЧЕМУ?
 ...
 // - а потому, что aRoot.Open('A') - доживает ДО СЮДА
 //   всё в соответствии со спецификацией - "если мы открыли "внутреннее хранилище", 
 //   то мы не можем открыть его снова, если мы его не отпустили"
end;

Как быть?

Тут варианта два. Оба они перечислены тут - Ответ на задачку №13

Так:

procedure ProcessStorage(const aRoot: ImyStorage);
var
 l_A : ImyStorage;
 l_A1 : ImyStorage;
 l_A2 : ImyStorage;
begin
 l_A := aRoot.Open('A');
 l_A1 := l_A.Open('1');
 // - тут всё хорошо, тут всё открылось
 l_A := nil;
 ...
 l_A := aRoot.Open('A');
 l_A2 := l_A.Open('2');
 // - тут всё хорошо, тут всё открылось
 l_A := nil;
 ...
end;

Или так:

procedure ProcessStorage(const aRoot: ImyStorage);

 function OpenInner(const aName: String): ImyStorage;
 begin//OpenInner
  Result := aRoot.Open('A').Open(aName);
 end;//OpenInner

var
 l_A1 : ImyStorage;
 l_A2 : ImyStorage;
begin
 l_A1 := OpenInner('1');
 // - тут всё хорошо, тут всё открылось
 ...
 l_A2 := OpenInner('2');
 // - тут всё хорошо, тут всё открылось
 ...
end;

Понимаю, что это всё - "повторение пройденного", но "повторение - мать учения".

Но это ещё не всё.

Продолжу в следующем посте.

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

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