![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Хрень с интерфейсом [D7, WinXP]
MgFox © (2004-12-30 10:20:00)Есть Интерфейс типа:
IMyIntf = interface
procedure callMe;
end;
класс к которому сий интерфейс привинчен
TMyClass=class(TObject,IMyIntf) ...
А экземпляр этого класса хранится не в обычной переменной я в переменной типа Pointer валяется на него ссылка.
И соответственно когда я пытаюсь обратиться к методу интерфейса
через указатель на объект
IMyIntf(ptr).callMe;
в ответ получаю Exception типа "Access violation ..."
Сообственно вопрос: как с этой хренью бороться ?
kull (2004-12-30 15:32:00) [1]Digitman все правильно написал, помоему этого достаточно.
Типа так и надо:
P: Pointer;
...
IUnknown(P) := MyInterface;
...
IUnknown(P) := nil;
...
Только на всякий случай надо в начале P := nil сделать, если не было раньше инициализации P, а то на присваивании
IUnknown(P) := MyInterface;
Может Exception случиться. Я уже сталкивался с этим.))
Cobalt (2004-12-30 12:59:00) [2]Digitman © (30.12.04 11:32) [13]
//интерфейс более не нужен - декрементируем сч-к ссылок
IMyIntf(SomeObject.Data)._Release;
Немного здоровой критики:
IMyIntf(SomeObject.Data):=nil;?
Erik1 (2004-12-30 11:50:00) [3]Непонятно что тебе точно нужно, но для общего развития: можно запросить интерфейс у объекта.
var
IPreview: IPreviewLayer;
begin
if Assigned(SomeObject.Data) and TObject(SomeObject.Data).GetInterface(IPreviewLayer,
IPreview) then
IPreview.Callme;
Digitman (2004-12-30 11:32:00) [4]
> я не могу
что это вдруг не можешь ? еще как можешь !
свойство типа Pointer ничем не отличается от переменной типа пойнтер , все практически так же будет выглядеть и в случае со св-вом ..
но я бы посоветовал наследовать свой TMyClass не от TObject, а от TInterfacedObject - там уже реализован подсчет ссылок и автоуничтожение объекта при сч-ке ссылок = 0
SomeObject.Data := Pointer(TMyClass.Create as IMyIntf); //происходит инкремент сч-ка ссылок
..
//вызываем интерфейсный метод
IMyIntf(SomeObject.Data).Callme; //инкремента сч-ка ссылок не происходит !
..
//интерфейс более не нужен - декрементируем сч-к ссылок
IMyIntf(SomeObject.Data)._Release;
Sandman25 (2004-12-30 10:51:00) [5]А вообще если есть общий предок, то интерфейсы не нужны. Достаточно описать виртуальный метод в предке.
Sandman25 (2004-12-30 10:50:00) [6][8] MgFox (30.12.04 10:41)
Значит нужно завести промежуточный класс с интерфейсом, или добавить поддержку интерфейса прямо в baseclass.
MgFox (2004-12-30 10:48:00) [7]to Palladin
//Идентификатор экземпляра класса сам по себе уже ссылка. Для чего тебе ссылка на ссылку? И если уж используешь это то и работай тогда с ней как с ptr^
Если я присваиваю указателю значение так:
ptr := TMyClass.Create();
как мне с ним работать ?
MgFox (2004-12-30 10:43:00) [8]to Digitman
я не могу его хранить как-то иначе чем через Pointer т.к. хранится оно не у меня, а в компоненте, в которой для хранения объектов есть аттрибутData:Pointer;
MgFox (2004-12-30 10:41:00) [9]to Sandman25
> Повторяю.
> (TMyClass(prt) as IMyIntf).Callme
так нельзя сделать т.к.
наследников базового класса у меня дцать и конкретный тип объекта, с которым осуществляется взаимодействие, неизвестен.
Для этого и был нарисован интерфейс дабы не париться с типом объекта.
Digitman (2004-12-30 10:38:00) [10]
> экземпляр этого класса хранится не в обычной переменной
> я в переменной типа Pointer валяется на него ссылка.
зачем хранить в переменной указатель на объект ? смысл какой ? ты же все равно будешь обращаться к этому объекту через его интерфейс ..
храни там, в переменной, прямо интерфейсную ссылку !
если заранее не знаешь, какой интерфейс там будет храниться, объяви как IUnknown, а в нужный момент приводи к нужному интерф.типу ... примерно так :
var
ptr: IUnknown;
..
ptr := TMyClass.Create;
..
IMyIntf(ptr).Callme
Palladin (2004-12-30 10:36:00) [11]
> Базовый класс не имеет такого интерфеса и при попыткке сделать
> IMyIntf(TBaseClass(ptr)).callMe;
А это вообще порнуха. Почему бы тебе не определить в таком случае этот интерфейс для базового класса? Если все же получение интерфеса проводится точно для именно правильного наследника то есть оператор AS и вообще приведение типов. Это первое. Второе
> А экземпляр этого класса хранится не в обычной переменной
> я в переменной типа Pointer валяется на него ссылка.
Идентификатор экземпляра класса сам по себе уже ссылка. Для чего тебе ссылка на ссылку? И если уж используешь это то и работай тогда с ней как с ptr^
Sandman25 (2004-12-30 10:36:00) [12]Повторяю.
(TMyClass(prt) as IMyIntf).Callme
MgFox (2004-12-30 10:33:00) [13]to Palladin
IMyIntf(ptr^).callMe;не спасает, результат тот-же - Exception
MgFox (2004-12-30 10:32:00) [14]Базовый класс не имеет такого интерфеса и при попыткке сделать
IMyIntf(TBaseClass(ptr)).callMe;
Delphi говорит что такое оно компилять не станет ибо типы IMyIntf и TBaseClass не совместимы.
PS: Сорри в исходном сообщении обшибочка
класс на самом деле делается так:
TMyClass=class(TBaseClass,IMyIntf) ...
Palladin (2004-12-30 10:25:00) [15]IMyIntf(ptr^).callMe; только зачем этот разврат...
Sandman25 (2004-12-30 10:22:00) [16](TMyClass(prt) as IMyIntf).Callme
А вообще лучше хранить в виде IMyIntF, а не pointer