Как заявил Тайлер Жандро, возможным решением является использование полиморфизма.
Но это требует тщательного планирования архитектуры и наследования классов, потому что, чтобы избежать использования понижающего приведения и огромного и необслуживаемого количества случаев switch(), вам также необходимо использовать полиморфизм в классах GUI.
Как того требует архитектура View/Model, классы данных будут имитироваться классами управления/графического интерфейса.
Классы данных будут реализованы с использованием предка, абстрактного класса CommonData
, который включает в себя общие «поля», и двух (или более) конкретных классов данных, полученных из CommonData
посредством наследования. Моя первая идея заключалась в том, чтобы вместо этого использовать композицию, но это создало бы другие проблемы при реализации графического интерфейса.
Таким образом, DataA
и DataB
являются производными от CommonData
.
Со стороны графического интерфейса структура аналогична, но из-за отсутствия поддержки наследования классов форм пользовательского интерфейса, сгенерированных Qt uic
, мы не можем использовать наследование. Мое первое предположение состояло в том, чтобы использовать метапрограммирование шаблонов и реализовать класс-предок как класс шаблона, но, хотя это работало на стороне C++, moc
отказывается анализировать этот класс и генерировать файл moc_X
, когда класс с тегом Q_OBJECT
является шаблоном.
Поэтому мы собираемся использовать сочетание наследования и композиции.
Это архитектура: «контейнерный» класс GUI (ContainerDialog
) реализует GUI для класса CommonData
; абстрактный класс PluggableInterface
будет определять набор операций (мы увидим ниже); набор конкретных классов, производных от последнего, будет реализовывать логику GUI для остальных классов.
Таким образом, ContainerDialog
загружает форму ContainerDialog.ui
как "стандартный" QDialog и управляет всем интерфейсом с помощью CommonData
. Его конструктор или сеттер получит указатель CommonData
, помните, что CommonData
является абстрактным и не может быть инстанцирован.
Конкретные поля управляются с помощью определенных графических компонентов, которые «подключены» к графическому интерфейсу ContainerDialog. Например, метод, определенный в PluggableInterface
, будет вставлять производный компонент QWidget в графический интерфейс ContainerDialog. Задействованные классы, например, ComponentA1
, ComponentA2
, ComponentB
и т.д....
Использование абстрактного интерфейса PluggableInterface
и компонентов пользовательского интерфейса не позволит ContainerDialog
узнать, какой тип конкретного класса используется, и весь необходимый код для создания экземпляров конкретных классов может быть реализован с использованием некоторого шаблона создания (абстрактная фабрика, прототипы и т. д.). ...)
person
HappyCactus
schedule
05.03.2015