Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.054 c
15-1155703959
MASTAFA
2006-08-16 08:52
2006.09.10
Скомпилированный файл справки. Как сделать?


3-1152072641
elyseev
2006-07-05 08:10
2006.09.10
Переиндексация DBF


15-1155651735
hamster
2006-08-15 18:22
2006.09.10
Не запускается Windows


15-1155609732
boalse
2006-08-15 06:42
2006.09.10
Unsafe code, как с этим бороться?


3-1152175448
WhiteBarin
2006-07-06 12:44
2006.09.10
Как получить скрипт вставляемой запись в БД через FIB+ ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский