Форум: "Основная";
Текущий архив: 2006.09.10;
Скачать: [xml.tar.bz2];
ВнизРеализация интерфейса Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.043 c