3

sorry if the title is a bit messy but I wasn't sure how to form my question. So I have some classes that I've used for a project that I'm looking to making more general so that I can reuse them for other projects. The idea was to move all code that is unique to the current project to a subclass of the original class. This has worked well for most parts since the most common way a function was made was that the general behaviour was first in the function and the program specific behaviour last. So in my new solution I just call the base class function from the subclass and then do the program specific code or the other way around. For example this:

void ParentClass::doStuff()
{
    doGeneralStuff();
    doprogramSpecificStuff();
}

Would become this:

void ParentClass::doStuff()
{
    doGeneralStuff();
}

void SubClass::doStuff()
{
    ParentClass::doStuff();
    doProgramSpecificStuff();
}

The problem arises when I have a function that looks like this:

void ParentClass::doOtherStuff()
{
    doOtherGeneralStuff();
    if (condition) {
        doEvenMoreGeneralStuff();
        doMoreProgramSpecificStuff();
    }
    doTheLastGeneralStuff();
}

Now the program specific code is in the middle of the function. One way to solve it would be to just copy the entire function to the subclass and remove the program specific line form the parent. But then I would end up with dublicated code and if I were to change the behaviour of my program down the line that could become a problem. I guess another way to solve it would be to call a function from the parent class that is empty but can be overwritten in a subclass if it wishes to do something at that point of the program. But that also seem kind of bad incase I end up with a lot of sub classes that all needs to do things like that. Then I would end up with a lot of just empty function calls.

Any advice how to solve this?

  • The correct solution is to use composition instead of inheritance. – gardenhead Mar 1 '17 at 15:55
4

The general solution to these problems is given by the Template Method design pattern.

Using this pattern, you can add extension points to your ParentClass where derived classes can 'inject' their own specific behavior, like this:

class ParentClass
{
public:
  void DoSomething()
  {
    doSpecificPreStuff();

    // do some generic stuff

    doSpecificMiddleStuff();

    // do some generic stuff

    doSpecificPostStuff();
  }
protected:
  virtual void doSpecificPreStuff() {}
  virtual void doSpecificMiddleStuff() {}
  virtual void doSpecificPostStuff() {}
};

class SubClass {
private:
  void doSpecificMiddleStuff() {
    // Do specific stuff
  }
  // Steps where no specific behaviour is needed are not overridden
};
2

While the premise seems like code smell to me, you can achieve something like this with the curiously recurring template pattern (CRTP). It allows the base class to depend on the derived class and have access to some of it's functionality.

template<class Derived>
class ParentClass
{
//...
}

class SubClass : public ParentClass<SubClass>
{
//...
} 

template<class Derived>
inline void ParentClass<Derived>::doOtherStuff()
{
    doOtherGeneralStuff();
    if (condition) {
        doEvenMoreGeneralStuff();
        static_cast<Derived*>(this)->doMoreProgramSpecificStuff();
    }
    doTheLastGeneralStuff();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.