Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос про интерфейсы


Страницы:   1 2

Суслик ©   (2005-10-07 13:09:00) 

Почему этот код

type
  IInterface1 = interface
     ['{E7550A1F-FE4B-410E-8EA0-E9882534AAE8}']
     procedure Do1();
  end;

  IInterface2 = interface(IInterface1)
     ['{FA7F65BF-93DC-4491-AC41-1D8970CCD649}']
     procedure Do2();
  end;

  TObject2 = class(TInterfacedObject, IInterface2)
     procedure Do1();
     procedure Do2();
  end;

procedure TObject2.Do1();
begin
  ShowMessage('1');
end;

procedure TObject2.Do2();
begin
  ShowMessage('2');
end;

procedure UseInterface1(I: IInterface1);
begin
  I.Do1();
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  I: IInterface2;
begin
  I := TObject2.create();
  UseInterface1(I);
end;


На строчке UseInterface1(I) не дает ошибку Interface not supported?
Хотя вроде должен...


Суслик   (2005-10-07 15:19:00) [21]


> UseInterface1(I)

здесь передается IInterface2


> UseInterface1(I AS Interface1)

здесь передается IInterface1


Digitman   (2005-10-07 15:01:00) [22]

но разницу в поведении программы в случае

UseInterface1(I)

и

UseInterface1(I AS Interface1)

ты, надеюсь, понимаешь ?


Digitman   (2005-10-07 14:54:00) [23]


> почему as не работает?


потому что AS приведет к вызову метода TInterfacedObject.QueryInterface() ... который в конечном итоге обратится к TObject.GetInterface, который в свою очередь обратится к GetInterfaceTable для получения таблицы интерфейсов, в которой, как ты правильно заметил, фигурирует лишь IInterface2

в случае же UseInterface1(I) обращение к InterfaceTable вообще не происходит


Суслик   (2005-10-07 14:52:00) [24]

Я вот и не могу понять концептуальную разницу в наслеловании интерфейсов и классов. Вернее интерфейсовклассов и интерфейсовинтерфейсов.


Digitman   (2005-10-07 14:51:00) [25]


> почему as не работает?


потому что AS приведет к вызову метода TInterfacedObject.QueryInterface() ... который в конечном итоге обратится к TObject.GetInterface, который в свою очередь обратится к GetInterfaceTable для получения таблицы интерфейсов, в которой, как ты правильно заметил, фигурирует лишь IInterface2

в случае же UseInterface1(I) обращение к InterfaceTable вообще не происходит


Суслик   (2005-10-07 14:47:00) [26]


> [7] Digitman ©   (07.10.05 14:21)

Я так понимаю, что в полиформизме классов и интерфейсов есть большая разница. Я что-то никак не могу ее ухватить :(


Суслик   (2005-10-07 14:33:00) [27]

Я с тобой в общем-то согласен. Я просто хочу понять, почему на мой взгляд все как-то нелогично. Почему as не работает? Почему явное приведение типов правильно? И


isasa   (2005-10-07 14:33:00) [28]

в явно???

TObject2 = class(TInterfacedObject, IInterface2, IInterface1)


Суслик   (2005-10-07 14:26:00) [29]


> да поддерживает же !


тогда почему as не работает?


Digitman   (2005-10-07 14:21:00) [30]


> Но с другой стороны этот же класс не поддерживает IInterface1
> (т.е. к нему нельзя сделать каст).


да поддерживаетже !

что ты говоришь-то ?

и как же незьзя сделать каст, кода можно и причем - запросто ?

вот смотри, как явноэто делается ("грязная работа"):

var
 I1: IInterface1;
 I2: IInterface2;

 I2 := TObject2.create();
 I1 := IInterface1(IUnknown(I2)); //можно и напрямую - IInterface1(I2), ничто в дан.случае этому не противоречит
 UseInterface1(I1); //и поехали !

в твоем же случае, т.е.

var
 I: IInterface2;
..
 I := TObject2.create();
 UseInterface1(I);

эту "грязную" работу неявно делает компилятор, ибо он достаточно "умный" и понимает, что ты требуешь от него вполне допустимое и реализуемое приведение типов ...


Суслик   (2005-10-07 14:18:00) [31]

Пардон, так верно

> Используй GetInterfaceTable и увидишь, что класс знает только
> о IInterface1.


Суслик   (2005-10-07 14:17:00) [32]


>  [4] Digitman ©   (07.10.05 14:13)


Используй GetInterfaceTable и увидишь, что класс знает только о IInterface2.
Поэтому невозможно сделать каст I as IInterface1. Попробуй.

Почему так? Почему I принимается в параметрах, где нужен IInterface1, но каст к IInterface1 невозможен?

Нелогично как-то.


Digitman   (2005-10-07 14:13:00) [33]


> Неверный ответ.


да ты что ?!) ... неужели ?)


> О первом интерфейсе (IInterface1) класс вообще не знает


здрасть !

а объявление и реализация процедуры Do1() в этом классе - это для Пушкина ?)

раз не знает, так убери попробуй !
зачем оно тебе, раз "не знает" ?)


Суслик   (2005-10-07 14:10:00) [34]

Извини, Сергей.

С


> Неверный ответ.


я скорее всего поторопился. Скорее - неполный ответ.

Вот смотри - с одной стороны класс поддерживающий IInterface2 подставляется в место, где трубется IInterface1. Но с другой стороны этот же класс не поддерживает IInterface1 (т.е. к нему нельзя сделать каст).

Как-то нелогично, я прошу объяснить смысл нелогичности.


Суслик   (2005-10-07 14:07:00) [35]


> TObject2 в дан.случае поддерживает и реализует оба интерфейса

Неверный ответ.

Поддерживает он только второй - см. GetInterfaceTable. О первом интерфейсе (IInterface1) класс вообще не знает.

Ты не сможешь сделать I as IInterface1 - будет interface not supported.

Судя по CPU компилятор лезет вызывать методы, предполагая, что они там есть. И более того вызывает их правильно. При этом никаких кастингов вообще не делает.


Digitman   (2005-10-07 13:20:00) [36]

потому что IInterface2 - наследник IInterface1

TObject2 в дан.случае поддерживает и реализует оба интерфейса


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо