2

也许这首先是糟糕的设计,但我有一个抽象基类,它有一个方法validate

public abstract class abClass{
  string str1;
  string str2;

  public virtual bool validate(){...};
}

我知道每个派生类都有需要验证的属性,但我不想复制粘贴每个抽象方法的str1验证str2

我想确保未来的开发人员(包括我自己)会记得包含并填写一个验证方法。从我所见,没有办法给抽象方法一个定义,或者强制一个虚拟方法被覆盖。

到目前为止,我听到的所有关于此的信息都是“你应该让开发人员选择他/她想要做的事情”。这对我来说还不够好,它违背了制衡,以帮助你不犯错误。我不介意他们是否主动选择没有任何实现代码,但如果他们忘记了,那么当派生字段未被验证时,这将导致头疼。

对这个问题有什么建议吗?

4

3 回答 3

6

您可以使用模板方法模式:

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();

这样,派生类必须重写ValidateOverride(因为它是抽象的),并且他们不能忘记调用ValidateCore,因为它是由基类中的非虚拟方法调用的。

于 2014-07-01T20:45:43.827 回答
5

Martin Fowler在他的CallSuper文章中讨论了这个确切的问题。

他基本上指出,在覆盖时要求类的子类调用基类方法是一种不好的做法或反模式:

Call Super 是一种在 OO 框架中不时出现的轻微气味(或反模式,如果您愿意的话)。它的症状很容易被发现。您从超类继承以插入某个框架。文档说类似“做你自己的事情,只需子类化 process 方法。但是重要的是要记住通过调用超类来启动你的方法”

他提出的解决方案是,基类应该自己做需要做的事情,而让派生类只关心派生类的问题:

相反,API 应该为您记住内务调用。执行此操作的常用方法是将句柄方法设置为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);
    }
}
于 2014-07-01T20:54:09.673 回答
0

你可以这样做:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            Base good = new Good();

            Base bad = new Bad();

            good.Validate();

            bad.Validate(); // This blows up

            Console.ReadLine();
        }
    }

    public class Base
    {
        public virtual void Validate()
        {
            throw new NotImplementedException();
        }
    }

    public class Good : Base
    {
        public override void Validate()
        {
            Console.WriteLine("Looks good to me.");
        }
    }

    public class Bad : Base
    {

    }
}

...虽然如果由我决定,我只会使用 Validate() 方法定义一个接口。

于 2014-07-01T20:49:57.910 回答