dimanche 17 janvier 2021

Arch. and code design. Should I be using concrete base classes or polymorphic one?

Well, i have the next C++ code:

#pragma once

#include "position_data.hpp"

#include <cstdint>

enum class e_color : uint32_t
{
    green = 0u,
    blue      ,
    red
};

class render_data_t
{

};

class render_2d_data_t : public render_data_t
{
public:
    float                   get_local_x()                         const
    {
        return 
            m_position.get_x();
    }

    float                   get_local_y()                         const
    {
        return 
            m_position.get_y();
    }

    void                    set_local_position( float x, float y )
    {
        m_position.set_x( x );
        m_position.set_y( y );
    }

private:
    position_2d_data_t  m_position;
};

class render_shape_2d_data_t  : public render_2d_data_t
{
public:
    e_color                 get_color()                     const
    {
        return m_color;
    }

    void                    set_color( e_color color )
    {
        m_color = color;
    }

private:
    e_color             m_color;
};

class render_shape_circle_t : public render_shape_2d_data_t
{
public:
    float                   get_radius()    const
    {
        return m_radius;
    }

    void                    set_radius( float radius )
    {
        m_radius = radius;
    }

private:
    float           m_radius;
};

class render_shape_rect : public render_shape_2d_data_t
{
public:
    float get_w()                           const
    {
        return m_w;
    }

    void  set_w( float w )
    {
        m_w = w;
    }

    float get_h()                           const
    {
        return m_h;
    }

    void  set_h( float h )
    {
        m_h = h;
    }

private:
    float   m_h;
    float   m_w;
};

Now, i want to create some Entity which will use this data by composition or aggregation.

class base_render_2d_entity_t        : public virtual base_position_2d_entity_t
{
public:
    using render_ptr  = std::unique_ptr<render_2d_data_t>;

    const render_2d_data_t     *get_render_data    ()                      const
    {
        return  
            m_render_data.get();
    }
          void                  set_render_position( float x, float y )         
    {
        m_render_data->set_local_position( x, y );
    }

private:
    render_ptr          m_render_data;
};

Great! I can create entities with circle or rectangle render data, and draw them by visitor or virtual draw method in these objects... But... In some day i want to change the radius of my render_circle_data, and i can't do it from base render class, cause we can have not only circle render data, but and rect render data. My question is:

Should i use double dispatching in the place where i want to change radius, or should i create some base interface(yes - pure virtual methods only, for get_render_data) and inherit from it the next classes:

base_render_2d_entity_t - for classes which can use all renders data, base_shape_render_2d_entity_t - for classes which can use only shape render data

???

Maybe there are other solutions to this problem?

Aucun commentaire:

Enregistrer un commentaire