类似于带有定义的抽象c#

本文关键字:抽象 定义 类似于 | 更新日期: 2023-09-27 18:10:58

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

public abstract class abClass{
  string str1;
  string str2;
  public virtual bool validate(){...};
}

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

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

到目前为止,我听到的所有关于这一点的说法都是"你应该让开发人员选择他/她想做什么。"这对我来说还不够好,它违背了帮助你不犯错误的制衡。如果他们主动选择不包含任何实现代码,我并不介意,但如果他们忘记了,那么当派生字段没有得到验证时,就会引起头痛。对于这个问题有什么建议吗?

类似于带有定义的抽象c#

你可以使用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();

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

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

他基本上指出,要求类的子类在重写时调用基类方法是一个不好的实践或反模式:

Call Super是在OO框架中不时出现的一种轻微的气味(如果您喜欢,也可以称为反模式)。它的症状很容易发现。为了插入某个框架,您正在继承超类。文档中有类似这样的内容:"要做自己的事情,只需创建进程方法的子类。然而,重要的是要记住在开始你的方法时调用超类"

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

相反,API应该为您记住内务管理调用。通常的方法是使句柄方法成为模板方法,如下所示:
//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);
    }
}

你可以这样做:

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()方法定义一个接口。