Mr.*_*ome 2 c# validation virtual-functions abstract-methods
也许这首先是糟糕的设计,但我有一个抽象的基类,它有一个方法 validate
public abstract class abClass{
string str1;
string str2;
public virtual bool validate(){...};
}
Run Code Online (Sandbox Code Playgroud)
我知道每一个派生类中都会有需要验证的属性,但我不希望有复制粘贴验证的str1和str2每个抽象方法.
我想确保未来的开发人员(包括我自己)会记得包含并填写验证方法.从我所看到的,没有办法给出一个抽象方法定义,或强制虚拟方法被覆盖.
到目前为止,我所听到的就是"你应该让开发者选择他/她想做的事情." 这对我来说不够好,它反对制衡,以帮助你不犯错误.我不介意他们是否积极选择没有任何实现代码,但如果他们忘记了,那么稍后在未验证派生字段时会引起头疼.
对此问题的任何建议?
您可以使用Template方法模式:
public bool Validate()
{
// Call base class validation
if (!ValidateCore())
return false;
// Call specific validation code (overridden by derived classes)
return ValidateOverride();
}
private bool ValidateCore()
{
// Validate str1 and str2
// ...
}
protected abstract bool ValidateOverride();
Run Code Online (Sandbox Code Playgroud)
这样,派生类必须覆盖ValidateOverride(因为它是抽象的),并且它们不能忘记调用ValidateCore,因为它是由基类中的非虚方法调用的.
Martin Fowler在他的CallSuper文章中讨论了这个问题.
他基本上声明,在重写时要求类的子类调用基类方法是一种不好的做法或反模式:
Call Super是一种在OO框架中不时出现的轻微气味(如果你愿意,也可以是反模式).它的症状很容易发现.你继承自一个超类,以便插入一些框架.文档说的是"做自己的事情,只是继承过程方法.但重要的是要记住通过调用超类来启动你的方法"
他提出的解决方案是基类应该自己做所需的事情,同时让派生类只关心派生类的关注点:
相反,API应该记住你的家政电话.通常的方法是使handle方法成为Template Method,如下所示:
//translation of java code to proper C#
public abstract class EventHandler ...
{
public void Handle (BankingEvent e)
{
HouseKeeping(e); //this is required by the base class.
DoHandle(e); //Here, control is delegated to the abstract method.
}
protected abstract void DoHandle(BankingEvent e);
}
public class TransferEventHandler: EventHandler
{
protected override void DoHandle(BankingEvent e)
{
initiateTransfer(e);
}
}
Run Code Online (Sandbox Code Playgroud)