Название: Классы-плагины Отправлено: Fregloin от Ноябрь 06, 2012, 18:27 Хай всем. Как можно реализовать полиморфизм в следюущей ситуации:
Есть общий предок ViewItem наследованный от QGraphicsObject. От ViewItem наследуется куча классов, задача которых отобрать на GraphicsScene различные графические объекты. Одни объекты могут менять свой цвет, фон, другие к томуже могут менять еще что то (например светофор, у которого есть несколько ламп, каждую из которых можно подсвечивать отдельно) или програсбар, в котором можно задавать текущее значение (int) и так далее. Так вот, я смотрю пока в сторону Q_INVOCABLE и работу с метаобъектами. Все графические классы хочу оформить в виде плагинов, так как в некоторых проектах набор этих классов может меняться (сейчас через define - но это ужас и я хочу от этого уйти). Есть еще логические объекты, которые собственно говоря и управляют графическим представлением. Хочется помаксимуму отойти к абстракции граф.объекта, но пока не знаю как сделать вызовы спецефичных для конкретных классов методов. Или в предке сделать что то типа virtual void setParam(имя параметра, сами параметры) = 0; а в наследниках уже разбирать эти параметры? Хотя как по мне это изврат... В какую сторону копать, где б что почитать в этом направлении. Графические и логические методы создаются соотвесвующими фабричными классами, хочется что бы они лежали каждый с своем плагине и основная програ ничего лишнего об их реализации не знала. пока все варится в одном проекте. Название: Re: Классы-плагины Отправлено: Bepec от Ноябрь 06, 2012, 19:31 Проще и короче.
Имеются классы графические и логические. Хочешь всё спрятать от пользователя. Ну так сделай интерфейс для обоих типов, там сделай виртуальные методы. Создавай свои классы, наследуясь от интерфейса. Будет стандартная основа и особенности для каждого класса. PS а уж где они будут решать тебе - плагины или обычные фабрики в dll/проекте. Название: Re: Классы-плагины Отправлено: Igors от Ноябрь 07, 2012, 09:40 Есть еще логические объекты, которые собственно говоря и управляют графическим представлением. Хочется помаксимуму отойти к абстракции граф.объекта, но пока не знаю как сделать вызовы спецефичных для конкретных классов методов. Или в предке сделать что то типа virtual void setParam(имя параметра, сами параметры) = 0; а в наследниках уже разбирать эти параметры? Хотя как по мне это изврат... В какую сторону копать, где б что почитать в этом направлении. Если говорить о данных (которые у каждого класса свои), то хост обычно хранит сериализованный экземпляр, напр в виде QByteArray, и никаких подробностей класса-плагина не знает.С методами сложнее. Это в учебных примерах все ложится в virtual draw, а в жизни получается класс вроде и общий, но имеет специфику. Для начала неплохо зарядить так Код Что-то типа Вындоуз месяг. Конечно это превратится в огромный свитч - ну это все равно лучше чем латания и приведения при каждом новом изменении ф-ционала. Более продвинутое решение - экспорт/импорт "интерфейса". Хотя здесь есть опасность увлечься красивыми идеями - и загубить проект. Хай всем. А не лучше ли использовать простые "здравствуйте", "добрый день", можно и "привет" :)Название: Re: Классы-плагины Отправлено: Fregloin от Ноябрь 07, 2012, 10:40 Добрый день ;D
Я так и понял, что скорее всего все сведется к многочисленным switch. Как вариант еще рассматриваю вызов методов через invokeMethod. Правда я этим еще ни разу не пользовался, на сколько они эффективны в плане производительности? Название: Re: Классы-плагины Отправлено: Igors от Ноябрь 07, 2012, 10:57 Как вариант еще рассматриваю вызов методов через invokeMethod. Правда я этим еще ни разу не пользовался, на сколько они эффективны в плане производительности? По существу вопрос "насколько быстрые слот/сигнал", что обсуждалось многократно :)Я так и понял, что скорее всего все сведется к многочисленным switch. Ну и что в этом такого уж плохого? На мой взгляд достоинства Qt сигналов сильно преувеличены :) Название: Re: Классы-плагины Отправлено: _OLEGator_ от Ноябрь 07, 2012, 11:21 Не обязательно в switch. Можно использовать контейнеры. У каждого объекта есть тип, при подгрузке плагина, узнавать у него тип и создавать контейнер связи типа с плагином. Потом при загрузке данных, вызывать конструктор у нужного плагина. Как то так.
Название: Re: Классы-плагины Отправлено: Fregloin от Ноябрь 07, 2012, 11:49 Можно по подробнее??
Название: Re: Классы-плагины Отправлено: _OLEGator_ от Ноябрь 07, 2012, 11:57 Что подробнее, тут уже нужно конкретно для задачи смотреть.
Абстрактно есть классы-плагины, с интерфейсами: - интерфейс получения типа класса. - конструктор класса, на вход которому допустим подается бинарный поток, для десериализации. Соответственно при загрузке приложения все такие плагины собираются в QMap, который хранит связь типа и плагина. Далее при загрузке данных используется только его тип, выбирается соответствующий плагин и на вход подается блок бинарных данных. Вся работа на уровне абстракций, никаких конкретных классов не используется, все только на уровне базовых классов. Тоже самое и при добавлении нового объекта нужного типа. Название: Re: Классы-плагины Отправлено: Fregloin от Ноябрь 09, 2012, 13:55 Вот что получается, к примеру:
Код: class RAILCORESHARED_EXPORT QAbstractRailItem : public QGraphicsObject, public QCommonRailItem Код: void QAbstractRailItem::executeCommand(const QString &commandName, const QVariant ¶ms) Название: Re: Классы-плагины Отправлено: Igors от Ноябрь 09, 2012, 14:51 У наследников довольно много параметров, все разные, получается много if()... как то совсем не красиво получается. А кто заставлял делать команду строкой? Просто int как 4-байтовая сигнатура, и незатейливый switch совсем неплох, напрКод Ну можно и мапу зарядить Код Так красивше, но отладка труднее. Вообще Ваш код смотрится, на мой взгляд, слишком "академично". Часто команда имеет 1 параметр, а иногда и вообще никаких - зачем такой жирный QVariant? Делая его константной ссылкой Вы вынуждены были добавить commandValue - не смертельно, но все-таки разрыв (чему оно соответствует если не было команды?). Гибче выглядит напр так Код В первую очередь нужен код возврата (команда прошла или нет). Также спорно нужен ли QVariant вообще - создавать структуры для команд так или иначе придется Название: Re: Классы-плагины Отправлено: Fregloin от Ноябрь 09, 2012, 15:06 Да дело в том, что хочется уйти от int. Раньше почти так и было, но во первых, в будущем возможно кто то плагигы будет дописыват вместо меня, плюс строки в гибкости. В интах лугече запутаться чем в строках. На счёт QVariant - хочется отойти от каких либо конкретных структур, что бы программа не знала о внутренней реализации каждого плагина, а вызывала все через вирутальный метод например так
someItem->setParam("color.main",someColor); QVariantMap map; map["color"] = Qt::red; map["lamp_index"]=12; someItem->setParam("color.lamp",map); и даже если пользователь ошибётся, то через QDebug или через код возврата сообщить об этом, но зато не нужно инклудить хидеры конкретной реализации. грубо говоря все делать через мета-свойства (не путать с QMetaObject). Я по крайней мере пока вижу так, а вот как реализовать перебором, думаю... Название: Re: Классы-плагины Отправлено: Igors от Ноябрь 09, 2012, 15:41 плюс строки в гибкости. В интах лугече запутаться чем в строках. Но минус в скорости и, еще важнее, в отладке. Использование 4-х байтовых сигнатур - стандартная практика на Mac, стоит попробовать, может понравится. 'LAMP', 'COLR' - достаточно понятно.На счёт QVariant - хочется отойти от каких либо конкретных структур, что бы программа не знала о внутренней реализации каждого плагина, а вызывала все через вирутальный метод например так Ну какие-то структуры так или иначе должны быть известны как плагину так и хосту, иначе как они могут обмениваться данными? Одеть все в QVariant эту проблему все равно не решает. map["lamp_index"]=12; Смысл понятен, не надо рихтовать структуры при всяком изменении. К сожалению, за эту гибкость придется платить - так оба (хост и плагин) просто помнят чему соответствует "lamp_index" в ихнем коде. На приемной стороне уже не получится так лихоКод И поиски "почему не работает" (а ошибок нет) могут быть долгими. Придется проверяться, теряя элегантность :) someItem->setParam("color.main",someColor); Код возврата: не нужно надеяться что все команды выполнятся без ошибок.Название: Re: Классы-плагины Отправлено: Fregloin от Декабрь 28, 2012, 12:26 все оказалось намного проще! воспользовался Q_PROPERTY! ;D
|