我正在创建一个C#框架,其中(几乎)所有类都将基于单个抽象基类。该基类包含一些私有设置属性,其中一个是布尔垃圾。
在XNA的绘制循环中,如果基类的 Garbage 属性设置为true,我不希望任何子类在各自的Draw()方法中执行代码。我尝试使用以下实现来执行此操作:
抽象基类:
public virtual void Draw(GameTime GameTime, SpriteBatch SpriteBatch)
{
if (Garbage) return;
}
继承类:
public void Draw(GameTime GameTime, SpriteBatch SpriteBatch, Color OverlayColor, float Scale)
{
base.Draw(GameTime, SpriteBatch);
//Other code here...
}
因为基类的Draw方法是在我的子类中的实际代码之前调用的,所以它会命中 return 语句,我希望这些语句可以进入我的子类的Draw()调用。但是,这种情况并没有发生。
有没有办法达到我想要的效果,而不添加“if(Garbage)return;”限制到每个继承类的Draw()方法的顶部?
答案 0 :(得分:5)
您可能考虑的一件事是有两种方法。您可以在抽象基础上使用Draw方法,该方法不会被覆盖,然后定义一个名为PerformDraw()的抽象受保护方法,您的继承者会覆盖它。
抽象基础绘图如下:
public void Draw(GameTime GameTime, SpriteBatch SpriteBatch)
{
if (!Garbage) PerformDraw(GameTime, SpriteBatch);
}
这使您可以覆盖绘制行为,但强制所有继承者使用“垃圾”检查。
答案 1 :(得分:4)
没有办法通过继承/多态来实现你想要的。我建议有一个实体管理器,其中包含所有想要绘制的对象,并且可以通过每个对象说出一些效果:
foreach (IEntity entity in _entities)
{
if(!entity.Garbage)
entity.Draw(....);
}
这种方式如果调用draw,对象可以做它应该做的事情并且垃圾被移动到不同的级别并允许它变得灵活,所以如果稍后你需要在对象可以绘制之前添加另一个子句,你只能需要更改1行代码,而不是每个绘制方法,并基本上得到你最初努力的效果。
答案 2 :(得分:3)
如果可能的话,您可能需要考虑Template Method Pattern。主要方法是:
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);
每个子类实现所需的DrawMe
方法(无可否认是一个糟糕的名字),你得到你想要的流程,而特定的类只知道如何绘制自己。
答案 3 :(得分:1)
如果您希望您的子类根据void
回复呼叫中父类的某些情况对函数调用进行保释,则您有以下选择:
1)检查子方法中的protected / public标志变量,然后检查分支逻辑。 AKA
// base class
if (Garbage) _someFlag = true;
// child class
base.Draw();
if(!_someFlag) // Do Stuff
2)在父类中抛出异常,这会阻止函数的其余部分执行(假设这适合您的情况)。
在您的特定情况下,您尝试通过void
方法将数据从父类返回到子类。如果这是我,我会做这样的事情:
// base class
public bool IsGarbage { get; set; }
// child class
public void Draw()
{
if(!IsGarbage)
{
// Do Stuff
}
}
答案 4 :(得分:1)
嗯,只是一个例子:
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
});
}
通过这种方式,您可以在一个的位置检查是否要绘制工件。
希望这有帮助。
答案 5 :(得分:1)
我认为你做的事情有点倒退。您最少重载的方法应该至少调用该调用,依此类推。
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
}