Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.01 c
11-56551
race1
2003-02-25 18:50
2003.11.17
component


3-56532
DmS
2003-10-27 13:19
2003.11.17
вопрос по Access у


14-56818
Nelud
2003-10-23 12:35
2003.11.17
Нужна здоровая критика!


1-56623
Mishenka
2003-11-07 18:59
2003.11.17
Как в ComboBox определить событие щелчка правой кнопкой?


3-56491
Ozone
2003-10-27 11:02
2003.11.17
ADO





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский