Форум: "Основная";
Текущий архив: 2003.11.17;
Скачать: [xml.tar.bz2];
ВнизДобраться до объекта реализующего интерфейс Найти похожие ветки
← →
kanych (2003-11-05 04:20) [0]Здравствуйте.
Может кто сталкивался с подобной проблемой.
Есть класс который реализует интерфейс:
type
TSBMessage = class(TAutoObject, ISBMessage)
private
FMessage: TIdMessage;
function GetMessage: TIdMessage;
protected
function Get_Sender: WideString; safecall;
procedure Set_Sender(const Value: WideString); safecall;
function Get_From: WideString; safecall;
procedure Set_From(const Value: WideString); safecall;
function Get_ReplyTo: WideString; safecall;
procedure Set_ReplyTo(const Value: WideString); safecall;
function Get_Recipients: WideString; safecall;
procedure Set_Recipients(const Value: WideString); safecall;
function Get_ReceiptRecipient: WideString; safecall;
procedure Set_ReceiptRecipient(const Value: WideString); safecall;
function Get_Subject: WideString; safecall;
procedure Set_Subject(const Value: WideString); safecall;
function Get_InReplyTo: WideString; safecall;
procedure Set_InReplyTo(const Value: WideString); safecall;
function Get_Body: WideString; safecall;
procedure Set_Body(const Value: WideString); safecall;
procedure Clear; safecall;
function Get_MessageParts: ISBMessageParts; safecall;
function Get_UID: WideString; safecall;
public
constructor Create(AOwner: TIdMessage = nil);
procedure Initialize; override;
property Message: TIdMessage read GetMessage write FMessage;
end;
А теперь я хочу добраться до свойства Message экземпляра этого класса имея интерфейс ISBMessage.
Такое возможно сделать? И если возможно, то каким образом?
← →
alex_*** (2003-11-05 09:04) [1]Нельзя. И это противоречит концепции интерфейсов.
← →
kanych (2003-11-05 09:12) [2]Спасибо, я уже разобрался.
Интересно, а чем это противоречит концепции интерфейсов? ;)
← →
alex_*** (2003-11-05 17:43) [3]Интерфейс для того и создан чтоб скрывать внутреннюю реализацию. Ты смог обратится?
← →
Dimka Maslov (2003-11-05 17:47) [4]Пытался я сделать такое. В принципе это возможно. Но мероприятие зависит от количества интерфейсов, реализуемых объектом (в том числе объявленных в классах-предках), а вот уже эту величину определить уже невозможно.
← →
nikkie (2003-11-05 17:48) [5]да нет проблем - as TSBMessage
концепции интерфейсов это не противоречит, но осадок неприятный :)
← →
Юрий Федоров (2003-11-05 17:57) [6]>>nikkie © (05.11.03 17:48) [5]
Неправда, это не откомпилируется
Елинственный вариант -
в интерфейс добавить метод
GetObject : TMyObject
(вернуть Self)
но в Com это недопустимо
← →
nikkie (2003-11-05 18:15) [7]>Неправда, это не откомпилируется
ну тогда TSBMessage(...)
← →
Ломброзо (2003-11-05 18:22) [8]> GetObject : TMyObject
а вернуть нетипизированный указатель? или адрес в long? )
>ну тогда TSBMessage(...)
AV
← →
vuk (2003-11-05 18:24) [9]to Ломброзо:
>а вернуть нетипизированный указатель? или адрес в long? )
Угу. Из другого процесса. :o)
← →
Ломброзо (2003-11-05 18:28) [10]Да что уж там, с другого хоста )
← →
Юрий Федоров (2003-11-05 18:29) [11]>>nikkie © (05.11.03 18:15) [7]
>>ну тогда TSBMessage(...)
Не пройдет, это будет совсем другой адрес. Даже в рамках одного процесса
← →
nikkie (2003-11-05 18:42) [12]
type
iZZZ = interface
procedure xxx;
end;
tZZZ = class(TInterfacedObject, iZZZ)
public
procedure xxx;
procedure yyy;
end;
procedure tZZZ.xxx;
begin
ShowMessage("xxx");
end;
procedure tZZZ.yyy;
begin
ShowMessage("yyy");
end;
procedure TForm1.Button1Click(Sender: TObject);
var
x: iZZZ;
begin
x := tZZZ.Create;
x.xxx;
tZZZ(x).yyy;
end;
проблем не наблюдается.
← →
Юрий Федоров (2003-11-05 18:49) [13]>>nikkie © (05.11.03 18:42) [12]
Это Compilier Magic
Посмотри, что он в Асме делает в ответ на этот код )))
← →
Ломброзо (2003-11-05 18:56) [14]имхо здесь компилятор просто знает смещение адреса интерфейса относительно адреса класса, потому что их описание находится в одном модуле, потому приведение типов работает корректно, за это спасибо компилятору. А вообще чревато ) Ср. с tZZZ(Pointer(x)) - шансы получить AV возрастают на порядок. Допустим, кто-то изменил реализацию класса, добавил пару полей, у него код более новый, а у вас старый. И вы генерируете TLB и делаете вот такое "насильное" приведение типов.
← →
vuk (2003-11-05 19:00) [15]to nikkie:
type
ISampleIntf1 = interface
["{38B86F8F-633D-4F01-A2BC-5C39330309A5}"]
procedure xxx;
end;
ISampleIntf2 = interface
["{9993B622-7946-4ECE-860D-F497B1FA7E5F}"]
procedure yyy;
end;
tZZZ = class(TInterfacedObject, ISampleIntf1, ISampleIntf2)
protected
FData: integer;
public
constructor Create(Data: integer);
procedure xxx;
procedure yyy; virtual; //<- Это имеет значение
end;
constructor tZZZ.Create(Data: integer);
begin
FData := Data;
end;
procedure tZZZ.xxx;
begin
ShowMessage("xxx " + IntToStr(FData));
end;
procedure tZZZ.yyy;
begin
ShowMessage("yyy " + IntToStr(FData));
end;
procedure TestProc(Ref: IUnknown);
begin
tZZZ(Ref).XXX;
tZZZ(Ref).YYY;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
x: ISampleIntf1;
begin
x := tZZZ.Create(1);
TestProc(x);
end;
← →
nikkie (2003-11-05 19:01) [16]какая разница, что он там делает? я догадываюсь, что VMT разные, поэтому реально это разные указатели. но ведь так сделать можно? и AV не будет.
← →
vuk (2003-11-05 19:24) [17]to nikkie:
Там даже не в VMT дело, а в том, что указатель на экземпляр и указатель на интерфейс, реализуемый этим экземпляром - это указатели в разные места. Со всеми вытекающими... А в Вашем примере все работало только потому, что методы статические и не используют данных экземпляра.
← →
nikkie (2003-11-05 20:51) [18]>Ломброзо
>И вы генерируете TLB...
вообще-то про COM и разные модули в теме ничего сказано не было... когда я говорил о приведении типов, подразумевал, что все происходит в одном модуле.
>vuk
пример убедителен. мне казалось, что если приведение iXXX(z) меняет значение указателя, то и tZZZ(x) также мог бы это делать, благо вся информация компилятору доступна.
кстати, в c++ преобразование проходит нормально в обе стороны
#include <stdio.h>
class iXXX {
public:
virtual char *xxx() = 0;
};
class iYYY {
public:
virtual char *yyy() = 0;
};
class ZZZ : public iXXX, public iYYY {
public:
int z;
ZZZ(int z) { this->z = z; }
char *xxx() { return "xxx"; };
char *yyy() { return "yyy"; };
};
void main()
{
ZZZ z(77);
iXXX *px = (iXXX *)(&z);
printf("%s\n", px->xxx());
iYYY *py = (iYYY *)(&z);
printf("%s\n", py->yyy());
ZZZ *pz;
pz = (ZZZ *)px;
printf("%s %d\n", pz->xxx(), pz->z);
printf("%s %d\n", pz->yyy(), pz->z);
pz = (ZZZ *)py;
printf("%s %d\n", pz->xxx(), pz->z);
printf("%s %d\n", pz->yyy(), pz->z);
printf("%d %d %d\n", px, py, pz);
}
результат работы:
xxx
yyy
xxx 77
yyy 77
xxx 77
yyy 77
1245044 1245048 1245044
← →
vuk (2003-11-05 20:54) [19]Угу. Потому, что классы - это не интерфейсы.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.11.17;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.009 c