I have an hierarchy of classes that looks like the following:
class Critical
{
public:
Critical(int a, int b) : m_a(a), m_b(b) { }
virtual ~Critical() { }
int GetA() { return m_a; }
int GetB() { return m_b; }
void SetA(int a) { m_a = a; }
void SetB(int b) { m_b = b; }
protected:
int m_a;
int m_b;
};
class CriticalFlavor : public Critical
{
public:
CriticalFlavor(int a, int b, int flavor) : Critical(a, b), m_flavor(flavor) { }
virtual ~CriticalFlavor() { }
int GetFlavor() { return m_flavor; }
void SetFlavor(int flavor) { m_flavor = flavor; }
protected:
int m_flavor;
};
class CriticalTwist : public Critical
{
public:
CriticalTwist(int a, int b, int twist) : Critical(a, b), m_twist(twist) { }
virtual ~CriticalTwist() { }
int GetTwist() { return m_twist; }
void SetTwist(int twist) { m_twist = twist; }
protected:
int m_twist;
};
The above does not seem right to me in terms of the design and what bothers me the most is
the fact that the addition of member variables seems to drive the interface of these classes
(the real code that does the above is a little more complex but still embracing the same pattern).
That will proliferate when in need for another "Critical" class that just adds some other
property.
Does this feel right to you? How could I refactor such code?
An idea would be to have just a set of interfaces and use composition when it comes to the base object
like the following:
class Critical
{
public:
virtual int GetA() = 0;
virtual int GetB() = 0;
virtual void SetA(int a) = 0;
virtual void SetB(int b) = 0;
};
class CriticalImpl
{
public:
CriticalImpl(int a, int b) : m_a(a), m_b(b) { }
~CriticalImpl() { }
int GetA() { return m_a; }
int GetB() { return m_b; }
void SetA(int a) { m_a = a; }
void SetB(int b) { m_b = b; }
private:
int m_a;
int m_b;
};
class CriticalFlavor
{
public:
virtual int GetFlavor() = 0;
virtual void SetFlavor(int flavor) = 0;
};
class CriticalFlavorImpl : public Critical, public CriticalFlavor
{
public:
CriticalFlavorImpl(int a, int b, int flavor) : m_flavor(flavor), m_critical(new CriticalImpl(a, b)) { }
~CriticalFlavorImpl() { delete m_critical; }
int GetFlavor() { return m_flavor; }
void SetFlavor(int flavor) { m_flavor = flavor; }
int GetA() { return m_critical-GetA(); }
int GetB() { return m_critical-GetB(); }
void SetA(int a) { m_critical-SetA(a); }
void SetB(int b) { m_critical-SetB(b); }
private:
int m_flavor;
CriticalImpl* m_critical;
};