Re[5]: Множественное наследование, mix-in-ы, traits
От: Kluev  
Дата: 10.05.06 18:25
Оценка:
Здравствуйте, iZEN, Вы писали:

ZEN>Здравствуйте, Kluev, Вы писали:


ZEN>У меня похожий образец UI в Java, но я обошёлся агрегированием вместо множественного наследования.

ZEN>Есть view — канва, на которой отображаются виджеты.
ZEN>Есть proxy_doc — синглетон-контейнер для однотипнах объектов-моделей — doc'ов в вашей терминологии.
ZEN>proxy_doc ничего не известно о конкретной моделе, но известно об области канвы; он может только правильно отрисовать модель, нуждающуюся в отрисовке (реконструировать dirty_doc, заодно "превратив" их обратно в doc ).

ZEN>Основной момент в таком образце: резко сокращаются накладные расходы на перерисовку всей сцены. Затрагивается только то, что действительно нуждается в обновлении. "Лишние" требования моделей на перерисовку себя отсекаются в proxy_doc и не приходят к view.


Я согласен что можно обойтись аггрегированием. А вместо вирутальных функций юзать делегаты. Или аггрегирование + наследование от интерфейса. Но это только workaround-ы, м-н подходит лучше.
Re: Множественное наследование, mix-in-ы, traits
От: Шахтер Интернет  
Дата: 10.05.06 20:34
Оценка: 34 (2)
Здравствуйте, VladD2, Вы писали:

VD>Хотелось бы услышать кто что думает по поводу необходимости подобных вещей в языках программирования.


VD>Особо привествуются примеры в которых данные фичи дают резкое упрощение решаемой задачи.


Допустим, у нас есть интерфейс

  interface IByteWriter
   {
    void put(byte b);
   }


Данный интерфейс я могу использовать как "базовый класс" при построении некоторой реализации класса -- потока байтов.

Мне хочется добавить в этот интерфейс некоторые воспомогательные функции, реализация которых основана на абстрактных методах, определённых в интерфейсе.
Например.

  interface IByteWriter
   {
    void put(byte b);
    
    struct UintToBytes
     {
      byte b1;
      byte b2;
      byte b3;
      byte b4;
      
      UintToBytes(uint u) { ... }
     };
    
    void put(uint w) 
     { 
      UintToBytes x=new UintToBytes(w); 
      
      put(x.b1); 
      put(x.b2); 
      put(x.b3); 
      put(x.b4); 
     }
   }


Естественно, в C# это не легально, и я вынужден заменить интерфейс абстрактным классом.

  abstract class IByteWriter
   {
    public abstract void put(byte b);
    
     struct UintToBytes
      {
       public byte b1;
       public byte b2;
       public byte b3;
       public byte b4;
      
       public UintToBytes(uint u) { ... }
      };
    
    public void put(uint w) 
     { 
      UintToBytes x=new UintToBytes(w); 
      
      put(x.b1); 
      put(x.b2); 
      put(x.b3); 
      put(x.b4); 
     }
   }


И тут я сталкиваюсь с проблеммой -- я могу унаследовать только от одного такого класса.
Если я в финальный класс захочу включить ещё один абстрактный базовый класс, например IStreamControl или IOutOfBandMessage, то у меня возникают траблы.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Множественное наследование, mix-in-ы, traits
От: IT Россия linq2db.com
Дата: 10.05.06 20:47
Оценка: +3 :))) :)))
Здравствуйте, Kluev, Вы писали:

K>
K>    : public QS_Object // базовый стафф
K>

Наиболее точный перевод слова 'стафф' с английского, передающий практически 100% смысл этого слова — это русское слово 'хрень'. Так бы сразу и писали — базовая хрень

Ничего личного, просто повеселило употребление stuff в таком виде
Если нам не помогут, то мы тоже никого не пощадим.
Re: Множественное наследование, mix-in-ы, traits
От: IT Россия linq2db.com
Дата: 10.05.06 21:24
Оценка: 26 (1)
Здравствуйте, VladD2, Вы писали:

VD>Хотелось бы услышать кто что думает по поводу необходимости подобных вещей в языках программирования.


1. Binding ASP.NET лучше всего работает с объектами, реализующими интерфейс ITypedList. Реализация этого интерфейса нетривиальна, но вполне возможна. Один раз реализовав TypedListImpl далее с помощью миксинов можно было бы подключать эту реализацию к нужным объектам. Сейчас это делается в базовом классе и с помощью копипейста переносится из проекта в проект.

2. При наличии соответствующих интерфейсов валидация тоже могла бы легко добавляться к объекту с помощью миксинов. Сейчас это делается так же в базовом классе.

3-й пример из той же серии — EditableObject. Причём, так как он всё равно работает только с абстрактными классами, а для них у нас уже есть реализация миксинов, то я в серьёз подумываю о том, чтобы прикрутить такую возможность к BLToolkit. Цель — высвободить базовый класс из пут фреймворка и оставить его в полном распоряжении разработчика.

4. Интерфейс IServiceProvider. Обычно каждый сервис реализует ещё и этот интерфейс, причём очень часто это простая делегация вызова к сервису, который зарегестрировал текущий сервис. Нужно реализовать всего лишь один метод, но с миксином было бы всё совсем просто.

VD>Особо привествуются примеры в которых данные фичи дают резкое упрощение решаемой задачи.


Не знаю наколько это было бы резким упрощением. Чаще всего это делается один раз в базовом классе, а для резкого упрощения нужно искать часто решаемые однотипные задачи.
Если нам не помогут, то мы тоже никого не пощадим.
Re: Множественное наследование, mix-in-ы, traits
От: c-smile Канада http://terrainformatica.com
Дата: 11.05.06 02:21
Оценка: 14 (1)
Здравствуйте, VladD2, Вы писали:

VD>Особо привествуются примеры в которых данные фичи дают резкое упрощение решаемой задачи.


Вот пример hello world из Harmonia:


Функциональность HtmlPanelT (html container) может
быть приделана к любому контейнеру виджетов:

Подмешивание методом curiously recurring template.

module samples.hello1;

// HTML Hello World.

import harmonia.ui.application;
import harmonia.ui.window;
import harmonia.html.view;

// HTML behavior can be attached to any container
// This time to the window.
alias HtmlPanelT!(Window) HtmlWindow;

void HelloWorldStart()
{
  HtmlWindow w = new HtmlWindow;
  w.html = 
     "<HTML back-color='edit info' 
            text-align=center 
            vertical-align=middle>Hello World!</HTML>";
  w.state = Window.STATE.NORMAL;
}

static this() 
{
  Application.onStart = &HelloWorldStart;
}


Второй пример опять же из Harmonia:

Здесь мы имеем классический пример когда на один класс
навешиваются различные свойства/имплементации из некоего конструктора.
Писать такое каждый раз — тоскливо.

В D нет множественного наследования (что есть хорошо)
поэтому mixin'ы естественный путь.


// Реализация свойства/состояния enabled 

template EnabledImpl()
{
  private bool _disabled;
  bool enabled() { return _disabled?false:true; }
  bool enabled(bool onoff) { _disabled = onoff?false:true; return enabled(); }
}


class EditBox: Widget, IValue, IInline, IProperties
{
public:
  mixin EnabledImpl!();
....
}

И еще куча widget derived классов


А это вот немного не в тему но тем не менее:
Это mixin выполняющий роль macro в С/С++,
в данном случае template traverser создает
локальную (inner) типизированную функцию traverseEvent


    // set the Widget in focus
    bool setFocus(Widget c, bool andCommandTarget = true)
    {
      mixin traverser!(EventWidget,Application.onEventWidget);

      if(c !is null)
      {
        _widgetEvent.type      = EventWidget.FOCUS_IN;
        if(!traverseEvent(_widgetEvent,c) || _widgetEvent.cancel)
          return false;
      }

      if(_focus !is null)
      {
        _widgetEvent.type      = EventWidget.FOCUS_OUT;
        if(!traverseEvent(_widgetEvent,_focus) || _widgetEvent.cancel) 
          return false;
      }
      return true;
    }


Ну и потом, какой крутой пацан без миксины?
Re[2]: Множественное наследование, mix-in-ы, traits
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.05.06 06:38
Оценка:
Здравствуйте, WolfHound, Вы писали:

Ты мог бы сформировать простой и наглядный пример?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Множественное наследование, mix-in-ы, traits
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.05.06 06:38
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ну, на конец то разумный пример без явных багов в проектировании. Реализация вспомогательных методов и частиченая реализация интерфейса — это хороший аргумент.
Отаровенно говоря мне за последние 5 лет такого не попадалось, но все же.

Вот только в Nrmerle есть маросатрибут [Nemerle.DesignPatterns.ProxyAllMembers()] который, если я верно понимаю позволяет решить проблему автоматически созадав обертки над методами и делегировав их вызовы вложенному объекту.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Множественное наследование, mix-in-ы, traits
От: Anton V. Kolotaev  
Дата: 11.05.06 06:39
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>В D нет множественного наследования (что есть хорошо)

CS>поэтому mixin'ы естественный путь.

CS>

CS>// Реализация свойства/состояния enabled 

CS>template EnabledImpl()
CS>{
CS>  private bool _disabled;
CS>  bool enabled() { return _disabled?false:true; }
CS>  bool enabled(bool onoff) { _disabled = onoff?false:true; return enabled(); }
CS>}


CS>class EditBox: Widget, IValue, IInline, IProperties
CS>{
CS>public:
CS>  mixin EnabledImpl!();
CS>....
CS>}

CS>И еще куча widget derived классов 

CS>


Как решается средствами D проблема, когда примесям надо обращаться друг к другу?

Т.е. есть ли альтернатива следующему основанному на CRTP коду?

template <class Derived>
    struct ImplA
{
    void f() { static_cast<Derived*>(this)->g(); }  
    void h();
};

template <class Derived>
    struct ImplB
{
    void g(); { static_cast<Derived*>(this)->h(); }
};

struct Component
    :  ImplA<Component>
    ,  ImplB<Component>
{};
... << RSDN@Home 1.2.0 alpha rev. 648>>
Re[3]: Множественное наследование, mix-in-ы, traits
От: Anton V. Kolotaev  
Дата: 11.05.06 06:50
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Вот только в Nrmerle есть маросатрибут [Nemerle.DesignPatterns.ProxyAllMembers()] который, если я верно понимаю позволяет решить проблему автоматически созадав обертки над методами и делегировав их вызовы вложенному объекту.


Правда, если у нас нет развитой макросистемы, то мы тут же начинаем заниматься набиванием кода проксей. А если макросистема есть, то imho любую задачу, решаемую МН, можно решить и макросами. Разве что только это решение может иметь высокую плату за вход.
... << RSDN@Home 1.2.0 alpha rev. 648>>
Re[3]: Множественное наследование, mix-in-ы, traits
От: c-smile Канада http://terrainformatica.com
Дата: 11.05.06 07:07
Оценка: 4 (1)
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Как решается средствами D проблема, когда примесям надо обращаться друг к другу?


AVK>Т.е. есть ли альтернатива следующему основанному на CRTP коду?


AVK>
AVK>template <class Derived>
AVK>    struct ImplA
AVK>{
AVK>    void f() { static_cast<Derived*>(this)->g(); }  
AVK>    void h();
AVK>};

AVK>template <class Derived>
AVK>    struct ImplB
AVK>{
AVK>    void g(); { static_cast<Derived*>(this)->h(); }
AVK>};

AVK>struct Component
AVK>    :  ImplA<Component>
AVK>    ,  ImplB<Component>
AVK>{};
AVK>



Норально решается. mixin's резолвятся во время последней фазы
компиляции. Поэтому такое вот работает:


template EnabledImpl()
{
  protected bool _disabled;
  bool enabled() { return _disabled?false:true; }
  bool enabled(bool onoff) { _disabled = onoff?false:true; return enabled(); }
}

template DisabledImpl()
{
  bool disabled() { return _disabled; }
  bool disabled(bool onoff) { _disabled = onoff; return disabled(); }
}


class EditBox: Widget, IValue, IInline, IProperties
{
public:
  mixin EnabledImpl!();
  mixin DisabledImpl!();

....
}
Re[4]: Множественное наследование, mix-in-ы, traits
От: Anton V. Kolotaev  
Дата: 11.05.06 07:17
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Норально решается. mixin's резолвятся во время последней фазы

CS>компиляции. Поэтому такое вот работает:


CS>
CS>template EnabledImpl()
CS>{
CS>  protected bool _disabled;
CS>  bool enabled() { return _disabled?false:true; }
CS>  bool enabled(bool onoff) { _disabled = onoff?false:true; return enabled(); }
CS>}
CS>


Если в конечном классе не будет члена _disabled, то в определении методов enabled имя _disabled свяжется лексически? Или будет ошибка?
... << RSDN@Home 1.2.0 alpha rev. 648>>
Re[2]: Множественное наследование, mix-in-ы, traits
От: _FRED_ Черногория
Дата: 11.05.06 07:56
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Пример #2

O>…А один базовый класс тут невозможен потому, что коллекция, ясен пень, унаследована от List<T>.

А зачем List<T> не предназначен для наследования. Для создания собственных коллекций с контролируемым поведением есть Collection<T>. В крайнем случае — собственноручная реализация IList<T>+IList.
... << RSDN@Home 1.2.0 alpha rev. 650>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Множественное наследование, mix-in-ы, traits
От: Oyster Украина https://github.com/devoyster
Дата: 11.05.06 08:02
Оценка:
Здравствуйте, _FRED_, Вы писали:

O>>Пример #2

O>>…А один базовый класс тут невозможен потому, что коллекция, ясен пень, унаследована от List<T>.

_FR>А зачем List<T> не предназначен для наследования. Для создания собственных коллекций с контролируемым поведением есть Collection<T>. В крайнем случае — собственноручная реализация IList<T>+IList.


Ну ладно — не List<T> (это я всех обманул ), а наш класс для списков... сути не меняет.
Re: Множественное наследование, mix-in-ы, traits
От: WoldemaR Россия  
Дата: 11.05.06 09:06
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Хотелось бы услышать кто что думает по поводу необходимости подобных вещей в языках программирования.


VD>Особо привествуются примеры в которых данные фичи дают резкое упрощение решаемой задачи.


Если выражаться общими словами, то можно сказать что множественное наследование рулит при описании ортогональной функциональности. Приведу пример из своей практики:
class LIKEVIEW_API Document : // Класс - Точка сборки
    public Object<LV_IDCLASS_DOCUMENT_BASE, Document>, // Объект создаваемый фабрикой
    public RefCounter,    // счётчик ссылок
    public Widget,        // базовый элемент ГУИ
    public Properties,    // контейнер свойств
    public Shape,         // фигура ГДИ
    public IdGenerator,   // генератор идентификаторов для сериализации связей
    public Port,          // узел графа схемы
    public Link,          // связь графа схемы
    public Executor       // исполнитель действий
{
// ...


В данном примере показано наследование для основного класса Document библиотеки LikeView.
Библиотека предназначена для построения интерактивных 2D графических приложений, представляет собой архитектурный каркас и расширяемый набор действий-утилит. На ней можно с одинаковым успехом писать векторные редакторы, редакторы схем, диаграмм и пользовательский интерфейс.

Если последовать традиционным путём полиморфного разделения функционала, то получился бы комбинаторный взрыв классов.

Таким образом по эффективности множественное наследование можно сравнить с операцией умножения.

А любители агрегирования получат тонны формального кода.

Предупреждаю об одном нехорошем свойстве данной архитектуры — это непредсказуемость.
Re[3]: Множественное наследование, mix-in-ы, traits
От: Kluev  
Дата: 11.05.06 10:04
Оценка: +2
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Шахтер, Вы писали:


VD>Ну, на конец то разумный пример без явных багов в проектировании. Реализация вспомогательных методов и частиченая реализация интерфейса — это хороший аргумент.


VD>Отаровенно говоря мне за последние 5 лет такого не попадалось, но все же.




VD>Вот только в Nrmerle есть маросатрибут [Nemerle.DesignPatterns.ProxyAllMembers()] который, если я верно понимаю позволяет решить проблему автоматически созадав обертки над методами и делегировав их вызовы вложенному объекту.


Танцы с бубном? А если вложенный обьект имеет виртульные функции которые необходимо переопределить в верхнем классе?

Тогда через делегаты и ручками, или вложенный обьект + верхний наследуем от интерфейса, сссылку на интерфейс передаем во вложенный обьект. Костыли и грабли налицо.

Множественное наследование отлично справляется когда есть иерархия классов и к некоторым из них нужно подключать функциональность которая не обеспечена основной иерархией. Т.е. если основная иерархия заточена под манипуляцию с данными, к одним классам добавляем визуализацию, к другим, что-то другое. Интерфейсы здесь не подходят т.к в одном флаконе требуются данные и реализация. Естественно проектировать классы надо с учетом того что они могут быть использованы во множ-наследовании.
Re[4]: Множественное наследование, mix-in-ы, traits
От: dshe  
Дата: 11.05.06 11:21
Оценка: 5 (1)
Здравствуйте, Kluev, Вы писали:

K>Множественное наследование отлично справляется когда есть иерархия классов и к некоторым из них нужно подключать функциональность которая не обеспечена основной иерархией. Т.е. если основная иерархия заточена под манипуляцию с данными, к одним классам добавляем визуализацию, к другим, что-то другое. Интерфейсы здесь не подходят т.к в одном флаконе требуются данные и реализация. Естественно проектировать классы надо с учетом того что они могут быть использованы во множ-наследовании.


Цели, ради которых и было придумано множественное наследование, вроде бы ясны. Однако, на мой взгляд множественное наследование реализации (по крайней мере в том виде, в каком оно реализовано в C++) чревато граблями больше, чем дает преимуществ. С МН возникает, так называемая, Diamond problem.
class A {};
class B: public A {};
class C: public A {};
class D: public B, public C {};

В приведенном примере объект класса D будет в себе содержать два экземпляра базового подобъекта класса A. Один унаследован от B, другой -- от C. иногда это бывает полезно, но иногда требуется только один базовый подобъект. В C++ это контролируется при помощи виртуального наследования.
class A {};
class B: public virtual A {};
class C: public virtual A {};
class D: public B, public C {};

В этом примере экземпляр класса D будет содержать только один базовый подобъект класса A.

Представим, что класс D (который наследуется от B, C) разрабатывает один разработчик и он понимает, что ему требуется иметь один подобъект класса A в D, т.е. ему необходимо виртуальное наследование. Вот тут возникает затык, поскольку ему необходимо будет менять классы B и C, а они могут разрабатываться другим разработчиком и эти классы могут поставляться без исходников. Т.е. разработчик классов B и C должен был бы заранее предусмотреть, что от них будут множественно наследоваться.

Следует также отметить, что для выражения отношения is-a стоило бы всегда использовать виртуальное наследование. Просто потому, что ну не может одна сущность являться другой несколько раз! Невиртуальное наследование отражает скорее отношение между классами has-a. Вот забавный пример, когда задумывалось множественное именно невиртуальное наследование.
class wheel {};
class first_wheel: public wheel {};
class second_wheel: public wheel {};
class third_wheel: public wheel {};
class fourth_wheel: public wheel {};
class vehicle: public first_wheel, public second_wheel, public third_wheel, public fourth_wheel {};

Здесь транспортное средство наследуется от четырех колес. Полагаю, что этот пример было бы более естественно переписать с использованием агрегации, а не наследования. Транспортное средство ведь не есть колесо четырежды, -- оно имеет четыре колеса.

Однако лично я редко видел, чтобы активно использовалось виртуальное наследование. По крайней в примерах кода в данном топике его по-моему не было ниразу. Должно быть, это из-за того, что виртуальное наследование бесплатно не дается и приведение к виртуальному базовому подобъекту менее эффективно, чем к невиртуальному. А может быть просто сила привычки.

Есть еще одна проблема с виртуальным наследованием: оно вынуждает классу знать не только о своих непосредственных предках, а и о всех своих виртуальных предках.
class A {
public:
    A(int) {}
};
class B: public virtual A {
public:
    B(): A(1) {}
};
class C: public virtual A {
public:
    C(): A(2) {}
};
class D: public B, public C {
public:
    D(): B(), C(), A(3) {}
};

При создании экземпляра класса D и инициализации единственного базового подобъекта A, какой конструктор должен Вызваться: A(1) или A(2)? Здесь решение принимается в классе D. Об этом можно не беспокоиться, если класс, унаследованный виртуально, имеет конструктор по умолчанию. Но в общем случае это добавляет лишние зависимости.

Резюмирую: для того, чтобы безопасно использовать МН в C++ необходимо чтобы у всех классов были конструкторы по умолчанию и все классы должны наследоваться виртуально. Мне кажется, что эти требования весьма жесткие.
--
Дмитро
Re[5]: Множественное наследование, mix-in-ы, traits
От: Kluev  
Дата: 11.05.06 12:32
Оценка: 1 (1) +3 -1
Здравствуйте, dshe, Вы писали:

D>Цели, ради которых и было придумано множественное наследование, вроде бы ясны. Однако, на мой взгляд множественное наследование реализации (по крайней мере в том виде, в каком оно реализовано в C++) чревато граблями больше, чем дает преимуществ.


Граблями черевато абсолютно все даже int,
надо юзать фичи там где они уместны и не юзать там где они неуместны.

Если м-н юзается чтобы соединить две ветвистые иерархии классов, то грабли обеспечены.
М-н совершенно безопасно если все подмешиваемые к одной иерархии классы sealed (т.е. спроектированы так чтобы не иметь наследников).
Re[3]: Множественное наследование, mix-in-ы, traits
От: migel  
Дата: 11.05.06 16:13
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, WolfHound, Вы писали:


VD>Ты мог бы сформировать простой и наглядный пример?

Зыыыыыы
    public interface IControl
    {
        #region General Properies
        /// <summary>
        /// Нечто, присоедененное к элементу управления
        /// </summary>
        [ReflectedDependency]
        [Browsable(false)]
        object Tag
        {get;set;}
        #endregion

        #region Information Properties
        #endregion
    }    
    public interface IButton : IControl
    {
        string Text
        {get;set;}
        
        event EventHandler Click;
    }

ну  и тд..

А теперь все это добро имплементим на основе WinForms
... << RSDN@Home 1.2.0 alpha rev. 644>>
Re[4]: Множественное наследование, mix-in-ы, traits
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.05.06 16:21
Оценка: 1 (1)
Здравствуйте, c-smile, Вы писали:

CS>Норально решается. mixin's резолвятся во время последней фазы

CS>компиляции. Поэтому такое вот работает:


CS>
CS>template DisabledImpl()
CS>{
CS>  bool disabled() { return _disabled; }
CS>  bool disabled(bool onoff) { _disabled = onoff; return disabled(); }
CS>}
CS>


То есть никакого контроля до использования, и в добавок прямое обращение к именам из внешних классов?

Мне кажется — это очень плохой дизайн. Ошибок будет много а и их поиск не прост.

В трэйтсах используемые из внешнего класса члены декларируются специальным образом, что снимает проблему. Но остается проблема разрешения конфликтов.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Множественное наследование, mix-in-ы, traits
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.05.06 16:21
Оценка: +1
Здравствуйте, WoldemaR, Вы писали:

WR>Если выражаться общими словами, то можно сказать что множественное наследование рулит при описании ортогональной функциональности. Приведу пример из своей практики:

WR>
WR>class LIKEVIEW_API Document : // Класс - Точка сборки
WR>    public Object<LV_IDCLASS_DOCUMENT_BASE, Document>, // Объект создаваемый фабрикой
WR>    public RefCounter,    // счётчик ссылок
WR>    public Widget,        // базовый элемент ГУИ
WR>    public Properties,    // контейнер свойств
WR>    public Shape,         // фигура ГДИ
WR>    public IdGenerator,   // генератор идентификаторов для сериализации связей
WR>    public Port,          // узел графа схемы
WR>    public Link,          // связь графа схемы
WR>    public Executor       // исполнитель действий
WR>{
WR>// ...
WR>


RefCounter в лес за недадобностью.
Document не имеет быть права контролом (Widget-ом) с точки зрения дизайна, в прочем как и фигурой (Shape) и исполнителем действий (Executor).
И того при нормальном дизайте этот класс будет вглядеть как-то так:
// Объект создаваемый фабрикой
[ClassFabric(X)]
class Document : SchemaNode
{
  Properties Properties { get { Properties(); } }
}


Вывод — очередная демонстрация того как МН приводит к ужасному дизайну "гэть в кучу".

WR>В данном примере показано наследование для основного класса Document библиотеки LikeView.

WR>Библиотека предназначена для построения интерактивных 2D графических приложений, представляет собой архитектурный каркас и расширяемый набор действий-утилит. На ней можно с одинаковым успехом писать векторные редакторы, редакторы схем, диаграмм и пользовательский интерфейс.

WR>Если последовать традиционным путём полиморфного разделения функционала, то получился бы комбинаторный взрыв классов.


Не... получился бы хороший дизайн намного более подходящий для дольнейшего развития.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.