Skip to main content
provided another suggestion
Source Link

One approach would be to make stuff more general in order to avoid casting to specific types.

You could implement a basic getter/setter of "dimension" float properties in the base class, which sets a value in a map, based on a a specific key for the property name. Example below:

class AbstractShape
{
public :
    typedef enum{
        SQUARE = 0,
        CIRCLE,
    } SHAPE_TYPE;

    AbstractShape(SHAPE_TYPE type):m_type(type){}
    virtual ~AbstractShape();

    virtual float computePerimeter() const = 0;
    
    void setDimension(const std::string& name, float v){ m_dimensions[name] = v; }
    float getDimension() const{ return m_dimensions[name]; }

    SHAPE_TYPE getType() const{return m_type;}
    
protected :
    const SHAPE_TYPE  m_type;
    std::map<std::string, float> m_dimensions;
};

Then, in your manager class you need to implement only one function, like below:

void ShapeManager::changeShapeDimension(const int shapeIndex, const std::string& dimension, float value){
   m_shapes[shapeIndex]->setDimension(name, value);
}

Example of usage within the View:

ShapeManager shapeManager;

shapeManager.addShape(new Circle());
shapeManager.changeShapeDimension(0, "RADIUS", 5.678f);
float circlePerimeter = shapeManager.computeShapePerimeter(0);

shapeManager.addShape(new Square());
shapeManager.changeShapeDimension(1, "WIDTH", 2.345f);
float squarePerimeter = shapeManager.computeShapePerimeter(1);

Another suggestion:

Since your manager only exposes the setter and the perimeter computation (which are exposed by Shape as well), you could simply instantiate a proper View when you instantiate a specific Shape class. EG:

  • Instantiate a Square and a SquareEditView;
  • Pass the Square instance to the SquareEditView object;
  • (optional) Instead of having a ShapeManager, in your main view you could still keep a list of Shapes;
  • Within SquareEditView, you keep a reference to a Square; this would eliminate the need of casting for editing the objects.

One approach would be to make stuff more general in order to avoid casting to specific types.

You could implement a basic getter/setter of "dimension" float properties in the base class, which sets a value in a map, based on a a specific key for the property name. Example below:

class AbstractShape
{
public :
    typedef enum{
        SQUARE = 0,
        CIRCLE,
    } SHAPE_TYPE;

    AbstractShape(SHAPE_TYPE type):m_type(type){}
    virtual ~AbstractShape();

    virtual float computePerimeter() const = 0;
    
    void setDimension(const std::string& name, float v){ m_dimensions[name] = v; }
    float getDimension() const{ return m_dimensions[name]; }

    SHAPE_TYPE getType() const{return m_type;}
    
protected :
    const SHAPE_TYPE  m_type;
    std::map<std::string, float> m_dimensions;
};

Then, in your manager class you need to implement only one function, like below:

void ShapeManager::changeShapeDimension(const int shapeIndex, const std::string& dimension, float value){
   m_shapes[shapeIndex]->setDimension(name, value);
}

Example of usage within the View:

ShapeManager shapeManager;

shapeManager.addShape(new Circle());
shapeManager.changeShapeDimension(0, "RADIUS", 5.678f);
float circlePerimeter = shapeManager.computeShapePerimeter(0);

shapeManager.addShape(new Square());
shapeManager.changeShapeDimension(1, "WIDTH", 2.345f);
float squarePerimeter = shapeManager.computeShapePerimeter(1);

One approach would be to make stuff more general in order to avoid casting to specific types.

You could implement a basic getter/setter of "dimension" float properties in the base class, which sets a value in a map, based on a a specific key for the property name. Example below:

class AbstractShape
{
public :
    typedef enum{
        SQUARE = 0,
        CIRCLE,
    } SHAPE_TYPE;

    AbstractShape(SHAPE_TYPE type):m_type(type){}
    virtual ~AbstractShape();

    virtual float computePerimeter() const = 0;
    
    void setDimension(const std::string& name, float v){ m_dimensions[name] = v; }
    float getDimension() const{ return m_dimensions[name]; }

    SHAPE_TYPE getType() const{return m_type;}
    
protected :
    const SHAPE_TYPE  m_type;
    std::map<std::string, float> m_dimensions;
};

Then, in your manager class you need to implement only one function, like below:

void ShapeManager::changeShapeDimension(const int shapeIndex, const std::string& dimension, float value){
   m_shapes[shapeIndex]->setDimension(name, value);
}

Example of usage within the View:

ShapeManager shapeManager;

shapeManager.addShape(new Circle());
shapeManager.changeShapeDimension(0, "RADIUS", 5.678f);
float circlePerimeter = shapeManager.computeShapePerimeter(0);

shapeManager.addShape(new Square());
shapeManager.changeShapeDimension(1, "WIDTH", 2.345f);
float squarePerimeter = shapeManager.computeShapePerimeter(1);

Another suggestion:

Since your manager only exposes the setter and the perimeter computation (which are exposed by Shape as well), you could simply instantiate a proper View when you instantiate a specific Shape class. EG:

  • Instantiate a Square and a SquareEditView;
  • Pass the Square instance to the SquareEditView object;
  • (optional) Instead of having a ShapeManager, in your main view you could still keep a list of Shapes;
  • Within SquareEditView, you keep a reference to a Square; this would eliminate the need of casting for editing the objects.
Source Link

One approach would be to make stuff more general in order to avoid casting to specific types.

You could implement a basic getter/setter of "dimension" float properties in the base class, which sets a value in a map, based on a a specific key for the property name. Example below:

class AbstractShape
{
public :
    typedef enum{
        SQUARE = 0,
        CIRCLE,
    } SHAPE_TYPE;

    AbstractShape(SHAPE_TYPE type):m_type(type){}
    virtual ~AbstractShape();

    virtual float computePerimeter() const = 0;
    
    void setDimension(const std::string& name, float v){ m_dimensions[name] = v; }
    float getDimension() const{ return m_dimensions[name]; }

    SHAPE_TYPE getType() const{return m_type;}
    
protected :
    const SHAPE_TYPE  m_type;
    std::map<std::string, float> m_dimensions;
};

Then, in your manager class you need to implement only one function, like below:

void ShapeManager::changeShapeDimension(const int shapeIndex, const std::string& dimension, float value){
   m_shapes[shapeIndex]->setDimension(name, value);
}

Example of usage within the View:

ShapeManager shapeManager;

shapeManager.addShape(new Circle());
shapeManager.changeShapeDimension(0, "RADIUS", 5.678f);
float circlePerimeter = shapeManager.computeShapePerimeter(0);

shapeManager.addShape(new Square());
shapeManager.changeShapeDimension(1, "WIDTH", 2.345f);
float squarePerimeter = shapeManager.computeShapePerimeter(1);