![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос про интерфейсы
Суслик © (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 в дан.случае поддерживает и реализует оба интерфейса