Russian Qt Forum
Апрель 26, 2024, 13:35 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблемы обобщения  (Прочитано 4537 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Декабрь 12, 2017, 10:00 »

Добрый день

Есть класс CGeometry (полигонный объект). Он управляется таким методом
Код
C++ (Qt)
void CGeometry::SetTransform(
const Coordinate & position,     // позиция объекта
const double angles[3],           // углы поворота
const double scale[3] );           // масштабы по осям
И есть класс камера для которого трансформация задается по-другому
Код
C++ (Qt)
void CCamera::SetTransform(
const Coordinate & position,     // позиция камеры
const Coordinate & reference,   // точка куда камера смотрит
double roll );                          // угол поворота вокруг оси зрения
И вот есть еще один класс CLight (источник света) для которого SetTransform задается точно так же как и для CCamera. Сейчас это решается просто дублированием кода (его не так уж много). Но все-таки интересно - а как грамотно (или правильно)? Очевидное наследование камеры и источника от одного базового класса (напр CReferenceObject) не нравится - слишком уж мало общего у этих классов (ну 5% отсилы) чтобы заряжать общую базу. Тогда какие еще возможности?

Спасибо
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #1 : Декабрь 12, 2017, 11:48 »

Здесь возможно несколько вариантов. Вот некоторые из них.

1. Наследование от общего интерфейса Transformable, который в общем случае будет абстрактным, а конкретная реализация  уточняться так называемыми деталями.

+ обобщение всех типов через общие интерфейсы Transformable и любой <Atribute>able.
+ сокрытие (как следствие, легкая замена) и множественность деталей реализации
- множественные наследования, сложность модели, определенный способ мышления (DDD).

2. Похожая реализация

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

3. Выделение отдельной сущности

В примере можно выделить отдельную сущность Transform, которая и будет нести в себе всю функциональность. Соберет разные реализации в одну сущность.
Тогда другие типы будут принимать только готовый экземпляр объекта Transform.

Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #2 : Декабрь 12, 2017, 13:01 »

Метод 1 - не сработает, т.к. интерфейсы должны быть разными.
Метод 2 - в принципе, для малой задачи самое оно. Но если вдруг "общее" разрастется - тогда плохо.
Метод 3 - вообще какой-то ад. Будет жуткий микс из кастов и свитчей.

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

Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #3 : Декабрь 12, 2017, 16:21 »

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

Это ж и есть методы 2 и 3). Только вместо CBaseTransform был предложен Transform, собирающий общий функционал по работе с трансформациями).
« Последнее редактирование: Декабрь 12, 2017, 16:23 от ssoft » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Декабрь 13, 2017, 08:21 »

Да, 3 выглядит самым идейным
Код
C++ (Qt)
class CTransformer {
 ...
 void SetGeometryTransform( const Coordinate & pos, const float angle[3], const float scale[3] );
 void SetReferenceTransform( const Coordinate & pos, const Coordinate & reference, double roll );
 ...
};
Ну и делать его членом CGeometry, CCamera, CLight и др. Тогда метод SetReferenceTransform можно использовать как для CCamera, так и для CLight.

Однако хранить сами данные (напр position, reference и др) этот новый класс вряд ли сможет. Надо делегироваться к объекту членом которого он является - и опять придется разбираться кто там CCamera или CLight.

Кстати общий базовый для всех объектов есть. И явно проще долить ф-ции SetTransform в базовый, плюс что-то типа virtual GetTransformType. Но так явно "god class"

 
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #5 : Декабрь 13, 2017, 08:34 »

Кстати общий базовый для всех объектов есть. И явно проще долить ф-ции SetTransform в базовый, плюс что-то типа virtual GetTransformType. Но так явно "god class" 

По хорошему, я бы рекомендовал пересмотреть объектно-ориентированную модель и перейти от наследования к агрегации. Но только если есть желание и время)).
Наличие у разнородных типов общего предка "god class" - это достаточно серьезное ограничение.

На счет "хранить сами данные (напр position, reference и др) этот новый класс вряд ли сможет" могу порекомендовать использовать для CTransformer PIMPL технику. Тогда в зависимости от внутреннего представления CTransformer может хранить совершенно разный набор данных.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #6 : Декабрь 13, 2017, 11:19 »

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

Это ж и есть методы 2 и 3). Только вместо CBaseTransform был предложен Transform, собирающий общий функционал по работе с трансформациями).

Просто Вы написали "Соберет разные реализации в одну сущность" - но по сути то реализация будет одна, для одного случая, а "не для всех возможных", когда без свитчей никак)
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.127 секунд. Запросов: 22.