Reputation: 2126
I'm creating a C# framework in which (nearly) all of my classes will be based off of a single, abstract base class. This base class contains some privately-set properties, one of which being the boolean Garbage.
In XNA's draw loop, I don't want any child classes to execute the code in their respective Draw() methods if the base class's Garbage property is set to true. I tried doing this with the following implementation:
Abstract base class:
public virtual void Draw(GameTime GameTime, SpriteBatch SpriteBatch)
{
if (Garbage) return;
}
Inherited class:
public void Draw(GameTime GameTime, SpriteBatch SpriteBatch, Color OverlayColor, float Scale)
{
base.Draw(GameTime, SpriteBatch);
//Other code here...
}
Because the base class's Draw method is being called before the actual code in my child class, it hits that return statement, which I would want to follow through into my child class's Draw() call. However, this isn't happening.
Is there any way to achieve the effect I want, without adding that "if (Garbage) return;" restriction to the top of every inherited class's Draw() method?
Upvotes: 3
Views: 2711
Reputation: 5325
I think your doing things a little backwards. Your least overloaded method should call the call the next least and so on.
public override void Draw(List<string> menuOptions, int currentSelection, MenuType type)
{
Draw("", menuOptions, currentSelection, type, Color.White, Color.Gray, Color.WhiteSmoke, Color.DimGray);
}
public void Draw(string menuName, List<string> menuOptions, int currentSelection, MenuType type)
{
Draw(menuName, menuOptions, currentSelection, type, Color.White, Color.Gray, Color.WhiteSmoke, Color.DimGray);
}
public void Draw(string menuName, List<string> menuOptions, int currentSelection, MenuType type, Color foreNorm, Color backNorm, Color foreSelect, Color backSelect)
{
//Actual Draw
}
Upvotes: 1
Reputation: 50225
If at all possible, you might want to consider the Template Method Pattern. Have the primary method be this:
public void Draw(GameTime gameTime, SpriteBatch spriteBatch, Color overlayColor, float scale)
{
if (Garbage) return;
DrawMe(gameTime, spriteBatch, overlayColor, scale);
}
protected abstract DrawMe(GameTime gameTime, spriteBatch SpriteBatch, Color overlayColor, float scale);
With each child class implementing the required DrawMe
method (admittedly a poor name), you get the flow you want and the specific classes only knowing how to draw themselves.
Upvotes: 4
Reputation: 62256
Well, just an example:
public class BaseClass
{
public bool Garbage {get;set}
}
//somewhere you have a collection of all artifacts to draw (children of BaseClass)
Lis<BaseClass> stuffToDraw = new List<BaseClass){....}
//and somewhere in the framewrok you have a method to draw them
public void Paint(...)
{
stuffToDraw.ForEach(stuff=>
{
if(stuff.Garbage) return;
stuff.Draw(....); //call of overriden virtual method
});
}
In this way you have one place where to check if to draw an artifact or not.
Hope this helps.
Upvotes: 1
Reputation: 4032
No there's no way through inheritance / polymorphism to achieve what you want. What I would suggest is having an Entity Manager that contains all your objects looking to draw, and can foreach through each saying something to the effect of:
foreach (IEntity entity in _entities)
{
if(!entity.Garbage)
entity.Draw(....);
}
This way if draw is called, the object can do what it's supposed to and the is garbage is moved to a different level and allows it to be flexible so if later you need another clause added before an object can draw, you only need to change 1 line of code, rather than each draw method and basically get the effect you were initially striving for.
Upvotes: 4
Reputation: 6090
One thing that you might consider is to have two methods. You could have your Draw method on the abstract base, which is not overridden, and then define an abstract protected method called PerformDraw() that your inheritors override.
Abstract base draw looks like:
public void Draw(GameTime GameTime, SpriteBatch SpriteBatch)
{
if (!Garbage) PerformDraw(GameTime, SpriteBatch);
}
This lets you override the draw behavior but forces all inheritors to use the "garbage" check.
Upvotes: 5
Reputation: 41246
If you want your child class to bail on the function call based on some situation in the parent class on a void
return call, your have the following choices:
1) Check a protected / public flag variable in your child method and then branch logic. AKA
// base class
if (Garbage) _someFlag = true;
// child class
base.Draw();
if(!_someFlag) // Do Stuff
2) Throw an exception in your parent class, which stops the rest of the function from executing (assuming this is appropriate to your situation).
In your particular case, you're trying to return data from the parent class to the child class through a void
method. If this was me, I would do something like this:
// base class
public bool IsGarbage { get; set; }
// child class
public void Draw()
{
if(!IsGarbage)
{
// Do Stuff
}
}
Upvotes: 1