3
// Car states : START, RUN, STOP


// START ==> RUN ==> STOP ==> Write
// CarFromStartToStop() :
// Car is initailly at STOP phase. 
// We start the and car comes in RUN phase.
// Then at the end car comes in STOP phase.
// WriteCarResults() : 
// Writes car's current status. eg : oil status, odometer etc.

class Info1 {
public:
  void Run(){
    CarFromStartToStop();
    WriteCarResults();
  }

private:
  void CarFromStartTopStop(){
    // Its own impelementation of how car will run.
  }
  void WriteCarResults(){
    // Write car's current status for running from start to finish.
  }

  Car c;

};

 

// RUN ==> STOP ==> Write
// CarFromRuningToStop() :
// The car is in RUN phase.
// Then at the end car comes in STOP phase.
// WriteCarResults() : 
// Writes car's current status. eg : oil status, odometer etc.

class Info2 {
public:
  void Run(){
    CarFromRuningToStop();
    WriteCarResults();
  }

private:
  void CarFromRuningToStop(){
    // Its own impelementation of how car will run.
  }
  void WriteCarResults(){
    // Write car's current status for running from start to finish.
  }

  Car c;

};

I have these two class. At first glance I would say we could use inheritance. They more of less do the same thing. They run the car and write data. But when I look close, I am not sure if inheritance is good choise.

Why?

Because the only method that are common (use same exact code) between two class is WriteCarResults. Other then that there is no code that are common.

My question: How can I make sure that I dont have to write the code that are common between the class (WriteCarResults).

Options:

  1. Use inheritance (for some reason I feel this approach is really contrived).

  2. Pull the writeCarResults() function out of the class. (I like this approach but not sure if this is a good one. Another problem I feel with this approach is WriteCarResults() should be part of the Info* class).

Please let me know if there is any design that would let me not write writeCarResults() function twice.

13

Believe it or not, what is truly hampering your design here is the names.

Info1 and Info2 are terribly meaningless, Run() steals its name from one of the car's phases yet covers all phases and more, and worst of all CarFromStartToStop() and CarFromRunningToStop() both leak implementation details making polymorphism imposible, whether you use inheritance or not.

A name should convey intent. It should ensure that what is found inside is not a surprise. But it should not tell you how. If it says how then implementation cannot change. Polymorphism means the implementation can change. Here's what happens when you follow these naming principles:

class StartToStopSimulator {
public:
  void Simulate(){
    OperateCar();
    WriteCarResults();
  }

private:
  void OperateCar(){
    c.Start();
    c.Run();
    c.Stop();
  }
  void WriteCarResults(){
    c.Status(outputPort);
  }

  Car c;

};

 

class RunningToStopSimulator {
public:
  void Simulate(){
    OperateCar();
    WriteCarResults();
  }

private:
  void OperateCar(){
    c.Run();
    c.Stop();
  }
  void WriteCarResults(){
    c.Status(outputPort);
  }

  Car c;

};

 

With these new names we're ready to refactor to use polymorphism.

class Simulator {
public:
  void Simulate(){
    OperateCar();
    WriteCarResults();
  }

private:
  void OperateCar(){
    operator.Operate(c);
  }
  void WriteCarResults(){
    c.Status(outputPort);
  }

  Car c;
  Operator operator;
  Output outputPort;
};

And you'd construct it like this:

Simulator sim = 
  new Simulator( 
    new CarCamaro(), 
    new OperatorSRS(), 
    new OutputConsole() 
  )
;

Now the Operator used decides what steps should be taken to operate the car. The two Operator classes will be different then the previous classes in that they will focus ONLY on the phases.

This is polymorphism through composition and delegation but you could have used inheritance here if you'd really wanted to. Composition usually proves to be more flexible. It just requires a little more keyboard typing.

  • Isn't this similar to decorator patter? By the way I should have some way to initialize the Operator operator variable right(via the Simulator's constructor)? eg : OperatorSSS operatorSSS; OperatorRSS operatorRSS; Simulator StartToStopSimulator(operatorSSS); Simulator RuningToStopSimulator(operatorRSS); ` I also have another question. Both OperatorSSS and OperatorRSS should inherit from Operator class right? – mato Apr 2 '18 at 3:49
  • 4
    A decorator pattern adds behavior while maintaining the same interface. What this does is push out the details of operating the car so the simulator has no knowledge of them. That way they can change without the simulator being touched. As for initialization: new Simulator( new CarCamaro(), new OperatorSRS(), new OutputConsole() ) Like Car, and Output, Operator can be an interface. – candied_orange Apr 2 '18 at 4:15
3

What CandiedOrange says.

Another observation: all the possible reasons you mention for using inheritance are wrong. You do not use inheritance to prevent duplicating code (that is just a natural consequence), you use inheritance when you spot an is-a relationship.

Is Info2 a (kind of) Info1? It is hard to tell. Your logic seems to be all about cars but I do not see a car class. As far as starting and stopping is concerned, logically, does it matter what type of car you are dealing with? What is a car result? Is it a move state? I do not understand much of the intended functionality from looking at your classes. This is what a class should provide, first and foremost. An outsider with a blank mind should understand what it đoes. If you fix that first, the rest will become easier.

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.