И нет такой директивы компилятора, о которой Дэнни думал, что она может существовать.
аружил (по крайней мере для меня) неожиданное поведение при использовании наследования интерфейса в Delphi.
У меня есть эта простая иерархия классов и интерфейсов:
+---------------+
| << IMyBase >> |
+---------------+
^
|
+---------------+
| << IMyIntf >> |
+---------------+
^
|
+---------+
| TMyObj |
+---------+
Я хотел объявить переменную типаIMyBase
, СоздатьTMyObj
и назначьте его моей переменной. IHMO это нормальная ООП практика. Но оказалось, что он не компилируется.
Я также пытался объявить переменную типаIMyIntf
и проверьте, поддерживает ли онIMyBase
ИМХО, это должно поддерживать, но это не так.
Вот простой тестовый код:
program interface_inheritance;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
IMyBase = interface
['{CC7C61B8-3FBA-481F-AF0D-A93C603B5202}']
procedure Hello;
end;
IMyIntf = interface(IMyBase)
['{01CE01D9-A753-431C-A30E-64BAEC6C4E26}']
//
end;
TMyObj = class(TInterfacedObject, IMyIntf)
procedure Hello;
end;
{ TMyObj }
procedure TMyObj.Hello;
begin
Writeln('Hello World');
end;
var
b: IMyBase;
i: IMyIntf;
begin
(* // Compile Error E2010
b := TMyObj.Create;
b.Hello;*)
// Does not work as Expected
// Does not call Hello()
i := TMyObj.Create;
if Supports(i, IMyBase, b) then begin
// Why does i not support IMyBase ??
b.Hello;
end;
// Works but unsafe!
// Hard cast, without check.
i := TMyObj.Create;
b := IMyBase(i);
b.Hello;
// Works, of course!
i := TMyObj.Create;
i.Hello;
Readln;
end.
Как вы можете видеть, у меня есть допустимая структура класса / интерфейса. но некоторые части не компилируются. а некоторые не выполняют, как ожидалось.
Почемуb := TMyObj.Create;
дать ошибку несовместимого типа?ПочемуSupports(i, IMyBase, b)
возвращаетсяfalse
?Есть ли другой (лучший) способ решить такую проблему? без жесткого броска без проверки? (if i is IMyBase
не работает, потому что интерфейсы не поддерживаютis
оператор).Это правильное поведение Pascal / Delphi или ошибка? ИМХОSupports()
должен вернутьсяtrue
, а такжеTMyObj
должен быть действительнымIMyBase
(и поэтому быть назначаемым).