Цитата:
Сообщение от dimarik
Термин - это точное определение понятия. Я не понимаю фразы "наследование через интерфейс".
|
В ООП существует термин "множественное наследование". Но многие языки (включая Си и Делфи) не разрешают наследоваться больше чем от одного предка (на мой вкус - это полезное ограничение). Зато эти же языки разрешают использовать сколько угодно интерфейсов. Таким образом, когда класс реализует несколько интерфейсов он получает несколько функциональностей, к которым можно обращаться по схеме, аналогичной тому, как если бы они являлись предками класса.
Возможно, термин "наследование через интерфейс" и не соответствует всем строгим критериям термина "наследования" (хотя, по-моему - вполне соответствует). В принципе - самым важным является, действительно, не факт "наследования", а возможность обращаться унифицированно к объектам разного типа. То есть речь идёт больше о полиморфизме.
Но с точки зрения программиста, удобно (по крайней мере - мне) рассуждать об использовании интерфейсов как о наследовании общего поведения от какого-то базового элемента.
Что важно в наследовании?
Пример (буду писать на дельфи, но и сишнику, уверен, будет понятно):

Код:
var c1: TClassA; // базовый класс
var c2: TClassB; // этот клас - наследник
begin
c1:= TClassA.create(); // это конструктор
c2:= TClassB.create(); // это конструктор
c1.someMethod(); // вызывается метод из TClassA
c2.someMethod(); // вызывается метод из TClassB
c1:= c2; // присваиваем переменну типа TClassB в тип TClassA
c1.someMethod(); // несмотря на то, что переменная c1 объявлена как TClassA - вызывается метод, объявленный в TClassB (если someMethod был объявлен как перегруженный)
end;
Это пример полиморфизма, реализованного с помощью наследования и перегрузки.
Аналогичный пример с интерфейсами:

Код:
var i1: IInterfaceA;
var i2: IInterfaceB;
var c1: TClassA; //этот класс реализует IInterfaceA
var c2: TClassB; //этот класс реализует IInterfaceB
var c3: TClassC; //этот класс реализует оба интерфейса
begin
c1:= TClassA.create();
c2:= TClassB.create();
c3:= TClassC.create();
i1:= c1;
i1.someMethod(); // вызывает реализацию метода из класса А, относящуюся к интерфейсу А
i1:= c3;
i1.someMethod(); // вызывает реализацию метода из класса С, относящуюся к интерфейсу А
i2:= c2;
i2.someMethod(); // вызывает реализацию метода из класса B, относящуюся к интерфейсу B
i2:= c3;
i2.someMethod(); // вызывает реализацию метода из класса С, относящуюся к интерфейсу B
end;
По внешнему виду этих 2 примеров видно, что по своему практическому поведению интерфейсы (использованные таким образом) идентичны множественному наследованию и позволяют применить те же самые приёмы программирования, что и в случае стандартного наследования.