![]() |
|
||||||||||
|
|||||
|
Негуру
администратор
Регистрация: Jan 2000
Адрес: Кёнигсберг in Moscow
Сообщений: 21,883
Записей в блоге: 7
|
Цитата:
|
|
|||||
|
Регистрация: Nov 2008
Сообщений: 528
|
"Множественное наследование (в классе) через реализации (в этом классе) интерфейсов". Сами интерфейсы реализации не несут, а вот "класс, реализующий интерфейсы" (даже не знаю, как назвать по другому - всегда так говорил) - эту реализацию как раз и обеспечивает.
|
|
|||||||
|
.
|
Цитата:
Термин - это точное определение понятия. Я не понимаю фразы "наследование через интерфейс". Я понимаю, что есть просто наследование. Я понимаю, что класс может реализовывать интерфейс. Так же я понимаю, что подкласс и так имеет методы суперкласса, навязанные интерфейсом, который реализует этот класс. Это и есть "наследование через интерфейс"? Ткните меня в это понятие, желательно в академической литературе, а не в досужих разговорах. Существенный плюс уже был описан. Цитата:
Предположим, в интерфейсе IMovable описан один метод moveTo. Класс машинки - Car. Цитата:
А вот базовый класс вертолета (Heliocopter) совсем отличается от базового класса машинки. Но вертолет и машика могут двигаться (moveTo). Теперь, предположим, что у нас есть два объекта: типа Heliocopter и Car. Как передать эти объекты обработчику движения, реализованному, предположим, в каком-то контроллере? Какой тип должен принимать этот обработчик? Вот теперь можно воспользоваться всей силой интерфейсов! Оказывается, оба объекта имеют тип интерфейса - IMovable. А обработчик выглядит так: Еще приятнее интерфейс проявляет себя при динамическом связывании, когда тип объекта не известен на этапе компиляции. Проверем объект на тип интерфейса, а не на тип его класса или суперклассов. Цитата:
Цитата:
Цитата:
Наследовать интерфейс можно только от интерфейса. |
|
|||||
|
Регистрация: Nov 2008
Сообщений: 528
|
Цитата:
В ООП существует термин "множественное наследование". Но многие языки (включая Си и Делфи) не разрешают наследоваться больше чем от одного предка (на мой вкус - это полезное ограничение). Зато эти же языки разрешают использовать сколько угодно интерфейсов. Таким образом, когда класс реализует несколько интерфейсов он получает несколько функциональностей, к которым можно обращаться по схеме, аналогичной тому, как если бы они являлись предками класса. Возможно, термин "наследование через интерфейс" и не соответствует всем строгим критериям термина "наследования" (хотя, по-моему - вполне соответствует). В принципе - самым важным является, действительно, не факт "наследования", а возможность обращаться унифицированно к объектам разного типа. То есть речь идёт больше о полиморфизме. Но с точки зрения программиста, удобно (по крайней мере - мне) рассуждать об использовании интерфейсов как о наследовании общего поведения от какого-то базового элемента. Что важно в наследовании? Пример (буду писать на дельфи, но и сишнику, уверен, будет понятно): 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;
Последний раз редактировалось Stargazer; 12.03.2009 в 23:01. |
|
|||||
|
Негуру
администратор
Регистрация: Jan 2000
Адрес: Кёнигсберг in Moscow
Сообщений: 21,883
Записей в блоге: 7
|
Ключевое в наследовании - это наследование. Когда вы реализовываете функционал описанный в интерфейсе, вы описываете его полностью с нуля. И когда у вас так "унаследовано" 200 классов и вы расширите этот интерфейс, вы будете править 200 классов. И когда вы делаете тоже самое, но без интерфейса, никто наследованием это не называет. Потому, что это не наследование, а просто реализация.
Поэтому, вещи надо называть своими именами, а не заниматься самообманом и словоблудием. |
|
|||||
|
Регистрация: Nov 2008
Сообщений: 528
|
Цитата:
Как один из вариантов (в делфи, по крайней мере) - можно использовать ключевое слово implements, которое позволяет назначить какое-нибудь поле как класс, отвечающий за реализацию интерфейса (удобно, когда один класс реализует сразу несколько интерфейсов). Таким образом я его буду описывать не с нуля, а на основе класса. Если потом вы расширите этот интерфейс - вам нужно переписать только один этот класс. Другой вариант (и часто более эффективный, в итоге) - просто создать базовый класс, который реализует интерфейс и от него создавать все другие классы. Пример (приведены только укороченные объявления): Type
TMyFirstClassA= class; // базовый класс
TMySecondClassA= class(TMyFirstClassA); // при помощи скобок в делфи указывается базовый класс по отношению к данному
TMyFirstClassB= class; // другой класс из другой иерархии
TMySecondClassB= class(TMyFirstClassB); // его наследник, соответственно
//Теперь предположим, что я решил, объединить их чем-то общим.
//Для этого я ввожу в цепочку классы, реализующие интерфейсы
IClassA= interface;
IClassB= interface;
TInterfacedClassA= class(TMySecondClassA, IClassA);
TInterfacedClassB= class(TMySecondClassB, IClassB);
TInterfacedClassAB= class(IClassA, IClassB);
//Ну и теперь я могу в своё удовольствие расширять функциональность, будучи уверенным, что мне не придётся "по 200 раз переписывать потомков"
TThirdClassA= class(TInterfacedClassA);
TThirdClassB= class(TInterfacedClassB);
TThirdClassAB= class(TInterfacedClassAB);
Поэтому давайте вы не будете спешить с выводами, насчёт того, как я себя самообманываю, насколько эффективным будет мой код на интерфейсах и сколько у меня будет лишней работы. P.S. добавил в пример множественное наследование. Последний раз редактировалось Stargazer; 13.03.2009 в 00:39. |
|
|||||
|
Негуру
администратор
Регистрация: Jan 2000
Адрес: Кёнигсберг in Moscow
Сообщений: 21,883
Записей в блоге: 7
|
Во-первых, у нас AS, а не дельфи. Поэтому у нас "своя, суверенная демократия". Вы будете описывать, описывать и еще раз описывать, то что заложено в интерфейсах.
Во-вторых, в моем примере, а это мой пример, что хочу, то с ним и делаю , изменения были не существенны и переписывать ничего не надо.Может сколько угодно рассуждать на эту тему, но наследованием тут и не пахнет. Последний раз редактировалось iNils; 13.03.2009 в 01:25. |
|
|||||
|
[+1 19.01.09]
[+1 17.03.09] Регистрация: May 2008
Сообщений: 27
|
Я и сейчас Сишник
на Флеше дома игрушку поделываю! |
![]() |
![]() |
Часовой пояс GMT +4, время: 20:04. |
|
|
« Предыдущая тема | Следующая тема » |
|
|