Как известно, в .net нет наследования класса от нескольких родительских классов. Это является темой бурных дискуссий, которые не являются темой данной ветки.
Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
16.12.05 16:43: Перенесено модератором из '.NET' — TK
Здравствуйте, Andrbig, Вы писали:
A>Как известно, в .net нет наследования класса от нескольких родительских классов. Это является темой бурных дискуссий, которые не являются темой данной ветки.
A>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
Да никогда оно не было нужно. Все делается с помощью интерфейсов и думаю это более прозрачно и наглядно. Вот когда интерфейсов не было может и возникла эта полемика.
Здравствуйте, снежок, Вы писали:
С>Здравствуйте, Andrbig, Вы писали:
A>>Как известно, в .net нет наследования класса от нескольких родительских классов. Это является темой бурных дискуссий, которые не являются темой данной ветки.
A>>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
С>Да никогда оно не было нужно. Все делается с помощью интерфейсов и думаю это более прозрачно и наглядно. Вот когда интерфейсов не было может и возникла эта полемика.
Я повторно напомню, что подобные дискуссии не являются темой данной ветки. Прошу в данном направлении ее не развивать.
Здравствуйте, снежок, Вы писали:
С>Здравствуйте, Andrbig, Вы писали:
A>>Как известно, в .net нет наследования класса от нескольких родительских классов. Это является темой бурных дискуссий, которые не являются темой данной ветки.
A>>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
С>Да никогда оно не было нужно. Все делается с помощью интерфейсов и думаю это более прозрачно и наглядно. Вот когда интерфейсов не было может и возникла эта полемика.
Даааа сильно задвинул — внушает
Очень сильно нужно именно при реализации интерфесов — миксинов когда нужна однообразная реализация для рахнотипных компонентов.
Например в нашем проекте обертки для контролов в дизайнерском режиме имеют сплошной CopyPaste
>>Например в нашем проекте обертки для контролов в дизайнерском режиме имеют сплошной CopyPaste
для чего люди придумали различные паттерны? adapter, bridge... Для того что бы мы продолжали заниматься copy/past?
Да, GUI наиболее сложно формализуемая вещь, но это не значит что каждую форму лучше лепить copy/past-ом.
Вот мне тут наставили минусов, а никто так и не объяснил для чего им множественное наследование, где они его пользовали?
Хотя может меня неправильно поняли. Есть множественное наследование интерфейсов, в сях есть множественное наследование классов. Я так понял что топик для дискусии по последнему (множ. насл. классов)
Стоит сказать что в шарпе вообще сказка, интерфейсы поддерживают не только методы, но и свойства. Ну и зачем вам после этого множественное наследование классов
>>Я повторно напомню, что подобные дискуссии не являются темой данной ветки. Прошу в данном >>направлении ее не развивать.
тема прозвучала как для чего нужно множественное наследование.
мой ответ — множественное наследование классов нигде не нужно, его возможности полностью покрывае использование интерфейсов. И чем я выбился из темы?
Здравствуйте, снежок, Вы писали:
>>>Например в нашем проекте обертки для контролов в дизайнерском режиме имеют сплошной CopyPaste С>для чего люди придумали различные паттерны? adapter, bridge... Для того что бы мы продолжали заниматься copy/past? С>Да, GUI наиболее сложно формализуемая вещь, но это не значит что каждую форму лучше лепить copy/past-ом. С>Вот мне тут наставили минусов, а никто так и не объяснил для чего им множественное наследование, где они его пользовали?
Какая нафиг форма
Есть задача обеспечить в дизайнере заданное поведение элементов управления — и как ты реализацию будеш интерфесом расширять?
Можно решить конечно предоставлением дизайнеру своего TypeDescriptor для адаптера заворачивающего нужный контрол, только, увы и ах, начинаються такие пляски с бубном .
С>Хотя может меня неправильно поняли. Есть множественное наследование интерфейсов, в сях есть множественное наследование классов. Я так понял что топик для дискусии по последнему (множ. насл. классов)
Не классов а реализации. С>Стоит сказать что в шарпе вообще сказка, интерфейсы поддерживают не только методы, но и свойства. Ну и зачем вам после этого множественное наследование классов
А затем чтобы миксин один раз написать и не парится.
например
class Base
{
public void Do() {}
}
class Mixin : IMixin
{
void IMixin.DoMixin(){;}
}
// вот тут впихиваем функционалclass C : Base, Mixin
{
}
без миксина получили бы вот такое
class C : Base, IMixin
{
void IMixin.DoMixin(){...;}
}
и теперь на уже существующию иерархии попробуй натянуть доп функционал без Copy Paste :-)
>>>Я повторно напомню, что подобные дискуссии не являются темой данной ветки. Прошу в данном >>направлении ее не развивать. С>тема прозвучала как для чего нужно множественное наследование. С>мой ответ — множественное наследование классов нигде не нужно, его возможности полностью покрывае использование интерфейсов. И чем я выбился из темы?
Приведенный выше пример показывает что это, несколько говоря, слишком сильное утверждение.
Здравствуйте, снежок, Вы писали:
С>тема прозвучала как для чего нужно множественное наследование. С>мой ответ — множественное наследование классов нигде не нужно, его возможности полностью покрывае использование интерфейсов. И чем я выбился из темы?
Я хотел узнать о примерах, а не о мнениях, хорошо это или плохо. Собсно это мнение начало дискуссию, взглянув на которую многим тему захотелось переместить в философию программирования.
А мне нафиг не нужна философия, я хотел узнать о примерах того, где множественное наследование классов помогло бы решить задачу.
>>>и теперь на уже существующию иерархии попробуй натянуть доп функционал без Copy Paste
для этого и были в C# 2.0 введены generics, как раз такого "алгоритмического наследования".
Здравствуйте, Andrbig, Вы писали:
A>Как известно, в .net нет наследования класса от нескольких родительских классов. Это является темой бурных дискуссий, которые не являются темой данной ветки.
A>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
Без множественного наследования, как и без ООП вообще, можно обойтись. Множественное наследование может упростить код, а может запутать.
abstract class Archived {
private boolean archived = false;
public void setArchived(boolean archived) {
this.archived = archived;
}
public boolean isArchived() {
return archived;
}
}
abstract class Managered {
private Manager manager = null;
public void setManager(Manager manager) {
this.manager = manager;
}
public Manager getManager() {
return manager;
}
}
abstract class PersistentWithLongId() {
private Long id = null;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
}
class ArchivedManageredPersistentWithLongId extends Archived, Managered, PersistentWithLongId {
}
В случае с интерфейсами (без множественного наследования) прийдется наследоваться от одного класса, два других делать интерфейсами и копировать реализацию сеттеров и геттеров в ArchivedManageredPersistentWithLongId.
Здравствуйте, снежок, Вы писали:
>>>>и теперь на уже существующию иерархии попробуй натянуть доп функционал без Copy Paste С>для этого и были в C# 2.0 введены generics, как раз такого "алгоритмического наследования".
то есть ты хочеш сказать что приведеный выше пример можно записать на дженериках так?
class Base
{
public void Do() {}
}
// вот тут впихиваем функционалclass C<T> : T, IMixin
{
void IMixin.DoMixin(){;}
}
Здравствуйте, Andrbig, Вы писали:
A>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
Пару раз, возникало в разработке GUI. Деталей уже не помню, давно это было. Проблема заключалась в том, что был нужен компонент, ведущий себя одновременно как два стандартных примитива. Решилась инкапсуляцией обоих классов в класс-обертку.
class Base
{
protected _mixin as IMixin;
public Base(IMixin mixin)
{
_mixin = mixin;
}
public void Do() {}
}
class Mixin : IMixin
{
void IMixin.DoMixin(){;}
}
class C : Base, IMixin
{
public C(IMixin mixin) : base(mixin)
{}
void IMixin.DoMixin(){ _mixin.DoMixin;}
}
...Ei incumbit probatio, qui dicit, non qui negat...
Здравствуйте, Andrbig, Вы писали:
A>Как известно, в .net нет наследования класса от нескольких родительских классов. Это является темой бурных дискуссий, которые не являются темой данной ветки.
A>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
При использовании стратегий, они подмешиваются mixin.
Для облегчения реализации Паттерна Декоратор.
Здравствуйте, Andrbig, Вы писали:
A>Как известно, в .net нет наследования класса от нескольких родительских классов. Это является темой бурных дискуссий, которые не являются темой данной ветки.
A>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
Есть вот такая техника программирования. Используется в ATL. Тут наследование на агрегирование не заменишь.
template<class T> class A{
public:
void do1(){
...
static_cast<T*>(this)->action1();
...
}
};
template<class T> class B{
public:
void do2(){
...
static_cast<T*>(this)->action2();
...
}
};
class MyClass : public A<MyClass>, public B<MyClass>{
public:
void action1(){
...
}
void action2(){
...
}
};
Здравствуйте, снежок, Вы писали:
С>Да никогда оно не было нужно. Все делается с помощью интерфейсов и думаю это более прозрачно и наглядно. Вот когда интерфейсов не было может и возникла эта полемика.
Ага. И ООП тоже в общем то никогда небыло нужно. Ведь все, в общем-то, делается простым вызовм процедур. Хотя... и процедуры в общем-то не нужны. Ведь хватает просто переходов (суловных и безусловных).
В общем ни один танкист не может понять зачем нужны дороги.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, last_hardcoder, Вы писали:
_>Есть вот такая техника программирования. Используется в ATL. Тут наследование на агрегирование не заменишь.
_>
_> static_cast<T*>(this)->action1();
_>
О! Вот это изумительный пример, эмуляции ООП не ОО-средствами.
Лет 7 тому назад когда я только увидел это дело в АТЛ я тоже был в восторке. Это же почти как с примененеием интерфейсов или виртуальных методов но без оверхэда на виртуальный вызов!
Потом понял, что дурь все это. Экономия от этого стремится к нулю, а вот дизайн получается кривой.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Andrbig, Вы писали:
A>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
Есть одна задача — подключение реализаций к классам.
Однако у МН куча своих проблем. Вместо МН предлагаются Mix-in-ы и Traits.
Погляди вот эти ссылки
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, last_hardcoder, Вы писали:
_>>Есть вот такая техника программирования. Используется в ATL. Тут наследование на агрегирование не заменишь.
_>>
_>> static_cast<T*>(this)->action1();
_>>
VD>О! Вот это изумительный пример, эмуляции ООП не ОО-средствами.
VD>Лет 7 тому назад когда я только увидел это дело в АТЛ я тоже был в восторке. Это же почти как с примененеием интерфейсов или виртуальных методов но без оверхэда на виртуальный вызов!
VD>Потом понял, что дурь все это. Экономия от этого стремится к нулю, а вот дизайн получается кривой.
Если говорить о размере ActiveX-ов, то экономия может получиться аж под 90%. При статической линковке таких GUI библиотек, как MFC или VCL в код лезут мегабайты. А на ATL может получиться всего сотня-другая кил. Не буду спорить о степени кривизны дизайна. Но на, мой взгляд, это недостаток языка программирования. А сама идея — не воспринимать команды программы буквально, отображая в соответствующий ассемблерный код, таблицы виртуальных методов, RTTI, а рассматривать их как набор формул, из которого компилятов выбирает только нужные для решения конкретной задачи и производит возможные сокращения на этапе компиляции — это движение в сторону языков следующего поколения, вроде PROLOG, декларативному программированию.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Andrbig, Вы писали:
A>>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
VD>Есть одна задача — подключение реализаций к классам.
Уточню , если правильно понял о чем речь.
Есть некие относледованные от базового ИНТЕРФЕЙСА классы , а мы хотим для них использовать одну СКРЫТУЮ реализацию. Т.е. то что в COM обычно делают темплейтами.
(на замену интерфейсов считаю был намек правильный). VD>Однако у МН куча своих проблем. Вместо МН предлагаются Mix-in-ы и Traits.
Класс.
А вообще множественное наследование могу терпеть только в условиях шаблонов(что проскакивает в ATL). Тогда действительно можно достаточно гибко резвиться. Иначе получается слишком жестко. Не люблю я такого.
Здравствуйте, last_hardcoder, Вы писали:
_>Если говорить о размере ActiveX-ов, то экономия может получиться аж под 90%.
Ну, размеры то от этого только вырастают. Ведь компилятор порождает специализации для любого сочетания типов. В некоторых случаях вообще возможен комбинаторный взрыв.
_> При статической линковке таких GUI библиотек, как MFC или VCL в код лезут мегабайты.
Сказок то ненужно рассказывать. Как раз при статической линковке лезут только используемые функции. Учитывая, что весь МФЦ это что-то около мега, то мегабайты лезть никак не могут. Там получаются сотни килобайт. К тому же МФЦ можно и одной ДЛЛ-кой бросить. К тому же причем тут МФЦ?
_> А на ATL может получиться всего сотня-другая кил.
Да, от того мы ее и использовали. Только вот когда проекты стали большими, то шаблонные специализации тоже начали проявляться и мы мало чего выиграли.
_> Не буду спорить о степени кривизны дизайна. Но на, мой взгляд, это недостаток языка программирования.
Язык вообще-то поддерживает виртуальные методы. Так что можно было бы делать и в ОО-стиле. Другое дело, что уж очень тянет "сэкономить".
_> А сама идея — не воспринимать команды программы буквально, отображая в соответствующий ассемблерный код, таблицы виртуальных методов, RTTI, а рассматривать их как набор формул, из которого компилятов выбирает только нужные для решения конкретной задачи и производит возможные сокращения на этапе компиляции — это движение в сторону языков следующего поколения, вроде PROLOG, декларативному программированию.
Не. Тут ты как раз ручками указывашь компилятору что нужно делать. Так что "это" движение в каменный век. Декларативность это как раз использвоание запросов вместо приказов.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, minorlogic, Вы писали:
M>Уточню , если правильно понял о чем речь. M>Есть некие относледованные от базового ИНТЕРФЕЙСА классы , а мы хотим для них использовать одну СКРЫТУЮ реализацию. Т.е. то что в COM обычно делают темплейтами.
Да, уж. Уточнил.
Ну, да это еще одно давление терминалогии и логики плюсов на восрпиятие окружающего мира. Я бы на сегодня сказал бы (по-моему) проще: Создание многократно используемых реализаций интерфейсов и подключение их к конкретным классам если в них требуется типовая реализация интерфейса.
В КОМ, конечно, это требуется в первую очередь, так как есть масса интрефейсов реализуемых почти что всегда однотипно. Но в принципе КОМ тут не причем.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, VladD2, Вы писали:
VD>>Есть одна задача — подключение реализаций к классам. GZ>Гадость. Лучше так — Re[2]: Mixins и рефакторинг
(на замену интерфейсов считаю был намек правильный).
Это несколько не то. Это не реализация интерфейса.
VD>>Однако у МН куча своих проблем. Вместо МН предлагаются Mix-in-ы и Traits. GZ>Класс.
К сожалению Хегельсберг сказал, что это слишком сложно для среднего американца. Надо бы его всенародно подолбить.
GZ>А вообще множественное наследование могу терпеть только в условиях шаблонов(что проскакивает в ATL). Тогда действительно можно достаточно гибко резвиться. Иначе получается слишком жестко. Не люблю я такого.
Невижу я ничего жесткого. Идея собирать классы из готовых, повторно используемых кусков — хорошая идея. Вопрос в простой реализации.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
GZ>>А вообще множественное наследование могу терпеть только в условиях шаблонов(что проскакивает в ATL). Тогда действительно можно достаточно гибко резвиться. Иначе получается слишком жестко. Не люблю я такого.
VD>Невижу я ничего жесткого. Идея собирать классы из готовых, повторно используемых кусков — хорошая идея. Вопрос в простой реализации.
Тут вопрос в полиформизме. Введении особых случаев. IMHO С шаблонами проходит проще чем через различные перегрузки функций.
VD>О! Вот это изумительный пример, эмуляции ООП не ОО-средствами.
VD>Лет 7 тому назад когда я только увидел это дело в АТЛ я тоже был в восторке. Это же почти как с примененеием интерфейсов или виртуальных методов но без оверхэда на виртуальный вызов!
VD>Потом понял, что дурь все это. Экономия от этого стремится к нулю, а вот дизайн получается кривой.
хм... неправда ваша...
в программировании на самом деле есть 2 понятия связывание и время связывания..
понимая где и как происходит первое и второе можно программировать на любом языке.( синтаксис можно поглядывать в справочнике)
так вот при написании вызва функций связывание происходит в момент написания кода
при вызове виртуальных функция в момент выполнения.
при вышеописанном способе ATL/WTL в момент КОМПИЛЯЦИИ.
так вот если все это правильно понимать и использовать это совсем не дурь каждое время связывания имеет свои особенности и плюсы и минусы, при правильно выбранном времени связывания код получается красивый, короткий, легкий для расширения, легкий для понимания, и производительный (с поправкой конечно на удобство программирование, на асме оно конечно быстрее будет ).
Здравствуйте, Andrbig, Вы писали:
A>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
Есть в .NET такой хорошо известный интерфейс IList. Его реализует куча классов как в самом .NET FW (от Array до List<T>), так и несчётное количество собственных поделок. Есть в .NET ещё два интерфейса: IBindingList и ITypedList. Первый — наследник IList, второй спроектирован более грамотно и содержит всего два необходимых метода. Оба интерфейса нужны для того, чтобы сделать списки связываемыми с пользовательским интерфейсом.
Так вот, проблема в том, что реализация последних двух интерфейсов не является тривиальной задачей. Но сделав это однажды, не было бы никаких проблем использовать это повторно для любых типов списков... если бы у нас было множественное наследование.
В результате мы имеем отсутствие (уже практически на протяжении 4-х лет) более менее нормальной реализации баиндига в .NET для объектов. Когда-то MS реализовал это для датасетов и до выхода 2-го фреймворка дело с места не двигалось. Во 2-м фреймворке определённый шаг вперёд сделан, но опять же по пути углубления иерархии, а не, как хотелось бы, расширения.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, VladD2, Вы писали:
VD>Невижу я ничего жесткого. Идея собирать классы из готовых, повторно используемых кусков — хорошая идея. Вопрос в простой реализации.
главный вопрос здесь — это как организовать взаимодействие между миксинами в пределах одного класса, и с самим классом-хозяином
в динамических яызках, насколько мне известно, этот вопрос решается очень просто — миксин может вызывать любые методы класса, в который его добавили. Но это, ИМХО, очень проблематично, если в классе случайно появится метод с совпадающим именем, но предназанченный разработчиком совсем для другой цели
более удачный вариант наверно такой:
public mixin Foo
{
// реализацияprotected abstract void Bar(); // <-- определить в классе, куда импортируется миксин
}
И еще надо как-то решать вопрос с совпадающими именами методов (хотя тут наверно можно сделать так же, как при явной реализации методов интерфейсов)
Здравствуйте, Дарней, Вы писали:
Д>главный вопрос здесь — это как организовать взаимодействие между миксинами в пределах одного класса, и с самим классом-хозяином
А в чём проблема?
Д>И еще надо как-то решать вопрос с совпадающими именами методов (хотя тут наверно можно сделать так же, как при явной реализации методов интерфейсов)
CLR может связывать любые методы совпадающие по сигнатуре с соответствующими методами интерфейса. Имена у таких методов тоже могут быть любые. Так что это не проблема. К тому же этим методам совершенно не обязательно торчать наружу из класса. Их задача — реализовывать конкретный интерфейс.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Дарней, Вы писали:
Д>главный вопрос здесь — это как организовать взаимодействие между миксинами в пределах одного класса, и с самим классом-хозяином Д>в динамических яызках, насколько мне известно, этот вопрос решается очень просто — миксин может вызывать любые методы класса, в который его добавили. Но это, ИМХО, очень проблематично, если в классе случайно появится метод с совпадающим именем, но предназанченный разработчиком совсем для другой цели Д>более удачный вариант наверно такой: Д>
Д>public mixin Foo
Д>{
Д>// реализация
Д>protected abstract void Bar(); // <-- определить в классе, куда импортируется миксин
Д>}
Д>
Ты примеры мои смотрел? Там именно это и предлагается.
Д>И еще надо как-то решать вопрос с совпадающими именами методов (хотя тут наверно можно сделать так же, как при явной реализации методов интерфейсов)
Тут нужен механизм переименования. Как правильно заметил ИТ, физических пробелм на уровне ЦЛР нет. А языковые можно решить введением неких атрибутов или еще как-нибудь.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
A>>Не расскажет ли уважаемый all о примерах, когда было нужно множественное наследование? (только просьба приводить реальные примеры)
IT>Есть в .NET такой хорошо известный интерфейс IList. Его реализует куча классов как в самом .NET FW (от Array до List<T>), так и несчётное количество собственных поделок. Есть в .NET ещё два интерфейса: IBindingList и ITypedList. Первый — наследник IList, второй спроектирован более грамотно и содержит всего два необходимых метода. Оба интерфейса нужны для того, чтобы сделать списки связываемыми с пользовательским интерфейсом.
IT>Так вот, проблема в том, что реализация последних двух интерфейсов не является тривиальной задачей. Но сделав это однажды, не было бы никаких проблем использовать это повторно для любых типов списков... если бы у нас было множественное наследование.
IT>В результате мы имеем отсутствие (уже практически на протяжении 4-х лет) более менее нормальной реализации баиндига в .NET для объектов. Когда-то MS реализовал это для датасетов и до выхода 2-го фреймворка дело с места не двигалось. Во 2-м фреймворке определённый шаг вперёд сделан, но опять же по пути углубления иерархии, а не, как хотелось бы, расширения.
IBindingList реализуется в коллекциях бизнес-объектов?