Наследование интерфейсов

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Аватара пользователя
and
постоялец
Сообщения: 124
Зарегистрирован: 16.09.2009 17:11:01
Откуда: г. Гомель, Беларусь

Наследование интерфейсов

Сообщение and »

Я чего-то не понимаю в работе с интерфейсами, или в FPC баг?

Код: Выделить всё

Program Project1;
{$mode objfpc}{$H+}
{$R *.res}
  Uses
    SysUtils;
  Const
    iid_Ancestor='{D9CB4FCD-A690-4A99-BD48-A1997AA970CF}';
    iid_Descendant='{621EAF8F-8E07-4BFD-A3F5-DBE359496A7E}';
  Type
{$INTERFACES COM}
    IAncestor=Interface
              [iid_Ancestor]
              End;
    IDescendant=Interface(IAncestor)
                [iid_Descendant]
                End;
    TImplementation=Class(TInterfacedObject,IDescendant)
                    End;
Begin
  WriteLn(Supports(TImplementation,iid_Descendant));
  WriteLn(Supports(TImplementation,iid_Ancestor))
End.
Вывод:

Код: Выделить всё

TRUE
FALSE
FPC 2.7.1 вчерашний.

Добавлено спустя 3 часа 11 минут 7 секунд:
Хмм... Проверил аналогичный код в Delphi. Поведение такое же: родительский интерфейс not supported. Выходит, баг в моём понимании интерфейсов, и тему можно крыть.
Под занавес ткните plz, где почитать здравое про подобные тонкости - в первую очередь, про наследование. Оно, как выясняется, несколько отличается от наследования у классов.
alexrayne
постоялец
Сообщения: 125
Зарегистрирован: 03.12.2008 15:56:26

Сообщение alexrayne »

Интерфейсы неимеют такой наследуемости как классы, т.е IDescendant не совместим с IAncestor.
в классе реализуемые интерфейсы задаются как перечень именно интерфейсов которые выставляет сам класс.
у Вас, класс выставил IDescendant как реализованый и именно к нему можно обратиться. IAncestor - не заявлен как реализованый классом, и к нему, соответственно, напрямую от класса обратиться нельзя. если IAncestor поддерживает методы получения себя самого, то можно получить IAncestor через какойто метод IDescendant (кажись Iuncknown имеет такие способности).
Аватара пользователя
Иван Шихалев
энтузиаст
Сообщения: 1138
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург
Контактная информация:

Сообщение Иван Шихалев »

alexrayne писал(а):IDescendant не совместим с IAncestor

Вот как раз на уровне языка он совместим, т.е. переменной типа IAncestor можно присвоить значение типа IDescendant.
А с реализацией — да, в таблицу интерфейсов класса попадает только непосредственно указанный. Можно просто добавить его в объявление:

Код: Выделить всё

    TImplementation=Class(TInterfacedObject,IAncestor,IDescendant)
                    End;

Хотя чаще удобно реализовать наследуемые интерфейсы в наследуемых классах...
Аватара пользователя
and
постоялец
Сообщения: 124
Зарегистрирован: 16.09.2009 17:11:01
Откуда: г. Гомель, Беларусь

Сообщение and »

Иван Шихалев писал(а):в таблицу интерфейсов класса попадает только непосредственно указанный. Можно просто добавить его в объявление
Да, это понятно, что можно вписАть его в шапку класса, и всё заработает. Тем более что класс в моём примере (есть цепочка наследования интерфейсов, но нет цепочки классов, реализатор только один) просто _не_может_ не реализовывать IAncestor: компилятор заругается. Отчасти поэтому для меня и стала сюрпризом необходимость прописывать IAncestor явно.
alexrayne
постоялец
Сообщения: 125
Зарегистрирован: 03.12.2008 15:56:26

Сообщение alexrayne »

Вот как раз на уровне языка он совместим, т.е. переменной типа IAncestor можно присвоить значение типа IDescendant.

Да, это дает некоторую иллюзию того что наследник и отец одной крови. Но когда дело доходит до реализации интерфейсов, особенно до получения интерфейса запросом к IUncknown, выясняется что можно реализовать их совершенно разными методами. тобиш родство по духу еще присутствует (состав интерфеса), а по плоти (интерфейс-потомок может иначе реализовываться чем отец) уже нет.
Особенно это забавляет когда глядиш как MSVCшные мастера создают интерфейсы к классам - там замечательно видна вся эта поднаготная.
Пока вы работаете в пределах паскаля, такие трюки вам попадаются редко, но как только вы пытаетесь работать с СОМ объектами написаными на MSVC то разницу между интерфейсами отцом и потомком надо всегда иметь в виду, и отождествлять их - ошибка.
Ответить