Why?

Ну, так или иначе все эти MFC-двойники уже не вставляют... ладно, в самом деле.

Традиционное GUI-приложение обычно устроено как большая, сильно полиморфная иерархия классов. Нередко в этом процессе задействован набор хорошо проработанных схем дизайна. В поддержку такой стратегии разработки созданы несколько огромных иерархических фреймворков, таких как MFC, wxWindows и т.д. Эти фреймворки содержат набор стандартных элементов GUI, которые можно использовать как базовые классы. Этот подход ("наследование") можно проиллюстрировать на примере с подгонкой фона кнопки.

//обычная кнопка
struct button
{
    ...свойства обычной кнопки
};


//кнопка с возможностью задать цвет фона
struct button_with_custom_background : button
{
    ...задать цвет фона
};

Допустим, нам понадобилась стандартная кнопка с картинкой. Мы можем создать другой класс кнопки.

//кнопка с картинкой
struct button_with_image : button
{
    ...задать способ отрисовки кнопки
};

Это сработало, но что если потом нам понадобится стандартная кнопка с возможностью задания цвета фона и картинкой. Очевидно, мы не сможем написать:

struct button_background_image
    : button_with_custom_background
    , button_with_image
{
    ...
};

Здесь проиллюстрирована общая проблема полиморфного наследования. Конечно, можно задействовать указатели, но это не будет хорошо выглядеть. Типобезопасность таких фреймворков не очень сильна, мягко говоря. Нотус предполагает другой подход. Он может быть описан как процесс задания набора взаимозаменяемых "деталей" GUI. Затем компилятор C++ генерирует и соединяет эти детали в соответствии с их спецификациями. Разумеется, спецификации описаны на языке шаблонов C++. Идея напоминает процесс промышленного производства, например такое, как разработка и создание автомобиля. В рассмотренном выше примере подход Нотус выглядел бы как следующий псевдокод.

struct my_background
{
    template< typename Window >
    void draw( Window& w ) {...}
};


struct my_image
{
    template< typename Window >
    void draw( Window& w ) {...}
};

Мы создали две взаимозаменяемые детали GUI. Они взаимозаменяемые, так как могут использоваться с любым окном, не только с кнопками, и легко могут быть заменены другой реализацией. Теперь мы можем соединить все детали вместе любым удобным нам способом.

typedef view< button
    , my_background > button_with_custom_background;

typedef view< button
    , my_image > button_with_image;

typedef view< button
    , my_background
    , my_image > button_with_background_and_image;

Мы можем сделать другие детали, например строку ввода с возможностью задания цвета фона.

typedef view< edit
    , my_background > edit_with_custom_background;

Since the final structure of the GUI application is generated at compile time, polymorphism is not an essential requirement anymore. Indeed, polymorphism is a way to abstract or classify a concrete class. Polymorphism is essential for traditional object oriented design because otherwise, we would have to implement separate routines for all possible concrete classes. With templates, we can just use the concrete classes directly and the compiler will generate code for each of the concrete combinations as needed. In Notus, a virtual method is an exception, not a rule.

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


© Copyright Евгений Гладышев, 2004

SourceForge.net Logo