Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's say I have a class called Country and two subclasses called AI and Player. The Country class has a number of virtual methods to allow player-specific or AI-specific behavior.

I want to make it possible for the player to switch countries during a game. To this end, I am refactoring the inheritance relation to composition. Then I will be able to switch out a Player's internal instance of Country for another at any time.

But this brings up a bit of a problem: When an external object attempts to call one of these virtual methods on a Player, it is delegated correctly to the Country method after any appropriate processing has been done. But when an internal Country method calls one of the virtual methods, the code in the Player or AI version no longer has a chance to run.

So now I'm left with updating every one of those methods to make sure both versions are called, which in itself is not a trivial task (infinite loops, anyone?).

This seems much harder than it ought to be. I've done similar refactorings before and never run into this issue. Why? Am I missing some blindingly obvious observation?


Edit for a concrete example now that I have access to the code again:

class Country
{
public:
    virtual void AddMoney(float money)
    {
        _vMoney += money;
    }
    void TakeLoan()
    {
        float loan = ...;
        AddMoney(loan); // <-- does not route through AI or Player implementation
    }
}

 

class AI  // : public Country
{
private:
    Country *pCountry;

public:
    virtual void AddMoney(float x)
    {
        pCountry->AddMoney(x); // formerly Country::AddMoney(x)
        AllocateMoney(x);
    }
}
share|improve this question

1 Answer 1

So let's make this concrete-ish.

class Country {
  virtual void foo();
  void bar() {
    foo();
  }
}

Moving toward:

class Country {
  private thingWhichWasSubclass;
  void bar() {
    thingWhichWasSubclass.foo();
  }
}

Is that right? How about as an intermediate step:

class Country {
  private thingWhichWasSubclass;
  void foo() {
    thingWhichWasSubclass.foo();
  }
  void bar() {
    foo();
  }
}

?

Would that do it? Then (of course) inline Country.foo().

share|improve this answer
    
(+1) For: "So let's make this concrete-ish." @mmyers, its ok to describe the problem, but if you do a small code example, along, it will be more clear to you and the readers. –  umlcat Jun 6 '11 at 23:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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