Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.09.10;
Скачать: CL | DM;

Вниз

Реализация интерфейса   Найти похожие ветки 

 
oleg___   (2006-07-27 13:26) [0]

Как сделать, чтобы класс, реализующий интерфейс, не уничтожался автоматически при нулевом количестве ссылок на интерфейс?


 
@!!ex ©   (2006-07-27 13:29) [1]

1) Написать свой класс.
2) А нафига?


 
oleg___   (2006-07-27 13:33) [2]


> 1) Написать свой класс.

В том-то и дело, что пишу свой.


> 2) А нафига?

класс используется даже тогда, когда нет ссылок на реализованный в нём интерфейс


 
@!!ex ©   (2006-07-27 13:39) [3]

>>В том-то и дело, что пишу свой.
Стоп-стоп.
С нуля пишешь или наследуешь от IUnknown?
Если с нуля, то не должно быть такой проблемы.
Если от IUnknown, то поидее никак. Потому что это реалиховано уже в нем.


 
Ruslan D   (2006-07-27 13:39) [4]

Думаю что никак, т.к. это одно из свойст ООП. Это типа автоматическое управление памятью.


 
@!!ex ©   (2006-07-27 13:43) [5]

Ruslan D
Не правильно думешь.
Это свойство не ООП, а класса IUnknown.


 
oleg___   (2006-07-27 13:44) [6]

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

TFirst = class(TAutoObject, IFirst)
 protected
 public
   constructor Create;
   destructor Destroy; override;
 end;

TSecond = class(TAutoObject, ISecond)
 protected
   FRef: TFirst; // ЭТОТ ОБЪЕКТ УНИЧТОЖАЕТСЯ АВТОМАТИЧЕСКИ, А ОН НУЖЕН
   function Get_Ref: IFirst; safecall;
 public
   procedure Initialize; override;
   destructor Destroy; override;
 end;

....



 
@!!ex ©   (2006-07-27 13:47) [7]

Как видно класс наследуеться от IFirst.
А у того уже забито внутри свойство убиваться когда ссылки кончаються.

Возможно это можно обойти, но ИМХО врядли.


 
oleg___   (2006-07-27 13:48) [8]

....когда пользователь через Get_Ref получает указатель на интерфейс IFirst, а потом перестает его использовать, то объект FRef автоматически удаляется - в этом проблема.


 
Юрий Зотов ©   (2006-07-27 13:58) [9]

> oleg___   (27.07.06 13:44) [6]

TSecond = class(TAutoObject, ISecond)
protected
  FRef: IFirst; // И объект уничтожаться не будет, т.к. на него висит ссылка
 ...
 end;


 
oleg___   (2006-07-27 14:04) [10]


> Юрий Зотов ©   (27.07.06 13:58) [9]

и доступа к членам класса TFirst тоже не будет, будет только к членам интерфейса IFirst.

Забыл сказать цель всего этого - у объекта TFirst есть свойства и методы, которые я не хочу светить в интерфейсе IFirst, но которые используются в классе TSecond.


 
Юрий Зотов ©   (2006-07-27 14:09) [11]

> oleg___   (27.07.06 14:04) [10]

Это другое дело. Но ведь можно сделать две ссылки  - одну объектную, а другую интерфейсную.


 
oleg___   (2006-07-27 14:22) [12]


> Юрий Зотов ©   (27.07.06 14:09) [11]

Да можно. Но в реальном проекте у меня массив таких объектных ссылок. Придется делать второй массив интерфейсных. Хотелось бы по-проще.


 
Romkin ©   (2006-07-27 14:31) [13]

А если не извращаться? Достаточно перекрыть addref & release у кокласса.
IUnknown - это не класс! Ну нет у интерфейса реализации.

TMyObj = class(TComObject, IMyIntf)
public
 function ObjAddRef: integer; stdcall; override;
 function ObjRelease: integer; stdcall; override;
end;
...
function TMyObj.ObjAddRef: integer;
begin
 Result := -1;
end;

function TMyObj.ObjRelease: integer;
begin
 Result := -1;
end;

В случае TAutoObject - просто пишите свои функции _Addref & _Release - интерфейс подцепит.

И не надо только мудрить!


 
Romkin ©   (2006-07-27 14:34) [14]

oleg___   (27.07.06 13:44) [6] а для этого случая уже Зотов ответил.
По идеологии тебе вообще может понадобиться агрегация, тогда AddRef & Release TFirst должны дергать эти функции у TSecond.


 
Медведъ   (2006-07-27 14:39) [15]

вызвать AddRed при создании


 
Юрий Зотов ©   (2006-07-27 14:43) [16]

> oleg___   (27.07.06 14:22) [12]

Интерфейсную ссылку можно завести где угодно, не обязательно в массиве. Хоть в самом объекте TFirst - главное, чтобы _AddRef щелкнул. Можно даже и не заводить ссылку, а просто вызвать _AddRef в конструкторе TFirst. Хотя это и дурной стиль, но цель будет достигнута - объект перестанет уничтожаться автоматически.

Но строго говоря, возникновение подобной проблемы обычно указывает на недостаточную продуманность структуры классов и/или интерфейсов. Было бы лучше не прибегать к сомнительным решениям, а пересмотреть эту самую структуру. Например, можно ввести еще один интерфейс, используемый только во внутренних целях - и пусть TFirst реализует оба интерфейса (а он и так их фактически реализует). Тогда FRef (или их массив) в TSecond будет содержать ссылку на этот служебный интерфейс - и все тип-топ.


 
oleg___   (2006-07-27 14:46) [17]


> Медведъ   (27.07.06 14:39) [15]
> вызвать AddRed при создании

имхо, вызывать AddRef без реальной ссылки может плохо кончится


 
Джо ©   (2006-07-27 14:50) [18]

> [13] Romkin ©  

Я тоже довольно часто так поступаю. В частности, когда нужно "привинтить" реализацию какого-то интерфейса к стандартному VCL-скому контролу. Часто это бывает форма, которой, разумеется, подсчет ссылок, как козе баян :) Оно, конечно, можно сделать, чтобы форма делегировала реализацию интерфейса какому-то другому классу; так, по-науке, оно, наверное было бы и правильнее, но — лень матушка :)


 
oleg___   (2006-07-27 15:11) [19]


> Юрий Зотов ©   (27.07.06 14:43) [16]


> Интерфейсную ссылку можно завести где угодно, не обязательно
> в массиве. Хоть в самом объекте TFirst - главное, чтобы
> _AddRef щелкнул. Можно даже и не заводить ссылку, а просто
> вызвать _AddRef в конструкторе TFirst. Хотя это и дурной
> стиль, но цель будет достигнута - объект перестанет уничтожаться
> автоматически.

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


 
Игорь Шевченко ©   (2006-07-27 15:13) [20]

А можно реализовать интерфейс в наследнике от TComponent


 
oleg___   (2006-07-27 15:19) [21]


> Игорь Шевченко ©   (27.07.06 15:13) [20]
> А можно реализовать интерфейс в наследнике от TComponent

у меня com-сервер


 
Юрий Зотов ©   (2006-07-27 21:05) [22]

> oleg___

Наверное, правильным, простым и удобным будет такое решение:

type
 IFirst = interface(...)
 ...
 end;

 IInternalFirst = interface(IFirst)
 ... // Расширение IFirst для внутреннего использования
 end;

 TFirst = class(TAutoObject, IFirst, IInternalFirst)
 ...
 end;

 TSecond = class(TAutoObject, ISecond)
 protected
   FRef: IInternalFirst;
   function Get_Ref: IFirst; safecall;
 ...
 end;


 
Deka ©   (2006-07-28 10:55) [23]

IClassFactory::LockServer
Called by the client of a class object to keep a server open in memory, allowing instances to be created more quickly.

А это не то? Метод LockServer() фабрики классов не позволяет выгрузить COM-объект даже когда он не используется...



Страницы: 1 вся ветка

Текущий архив: 2006.09.10;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.034 c
1-1154237394
tio
2006-07-30 09:29
2006.09.10
Вывод окна на передний план


3-1151744812
Lis'S
2006-07-01 13:06
2006.09.10
Пробелы в таблицах БД


2-1156314634
Андрей Пазик
2006-08-23 10:30
2006.09.10
Создание кросс-массива


15-1155985488
Nic
2006-08-19 15:04
2006.09.10
Наручные механические часы


3-1152007567
drashka
2006-07-04 14:06
2006.09.10
Ошибка при использованиии запроса Like с русским текстом