【问题标题】:C# Abstract function with implementation possible?可以实现的 C# 抽象函数?
【发布时间】:2011-10-10 18:54:25
【问题描述】:

有没有办法添加一个必须被所有继承类覆盖的虚函数?那么实际上是虚拟和抽象的结合吗? 我有一种情况,每个继承的类必须在执行一些通用代码之前进行一些特定的处理。虚函数不起作用,因为它们不能确保继承的类会覆盖它们。抽象函数不能有默认实现。目前我的解决方法是在包含通用/通用代码的基类中实现另一个受保护的函数,并在覆盖的抽象函数中调用

【问题讨论】:

  • 如果它有一个默认实现,为什么它需要被覆盖?这不是违背目的吗?如果它总是会被覆盖,为什么不让它抽象呢?
  • 当你重写函数时,就可以改变body。您不能更改方法签名。

标签: c# virtual abstract


【解决方案1】:

不可能有一个既是抽象又是虚拟的方法。

如果可能,您可以将方法拆分为“之前”和“之后”部分:

public void DoWork()
{
    DoBeforeWork();
    DoCommonWork();
    DoAfterWork();
}

protected abstract void DoBeforeWork();
protected abstract void DoAfterWork();

private void DoCommonWork() { ... }

否则,使用第二种受保护方法的解决方法是一个非常好的主意:

public void DoWork()
{
    DoActualWork();
}

protected abstract void DoActualWork(); // expected to call DoCommonWork

protected void DoCommonWork() { ... }

如有必要,您可以使用线程本地字段检查 DoCommonWork 是否真的在 DoWork 中被调用。

但是,我可能会采用虚拟方法。如果派生类不想向公共部分添加任何内容,则不必:

public virtual void DoWork() { ... }

同样,你可以检查公共部分是否真的被调用了。

【讨论】:

  • +1 作为你的第一个例子,尽管第二个例子几乎想去-1,因为它和原始问题一样不安全,非常危险。不必记住重写虚函数,我们现在必须记住从抽象函数中调用 DoCommonWork。您的第一个示例可以减轻任何此类风险。
  • 我想我赞成你的第一个建议。这种构造是安全的,因为保证调用公共代码并且必须在派生类中实现抽象的 DoBeforeWork 函数。
【解决方案2】:

我认为您可能正在寻找template method:在您的基类中实现一个方法,该方法调用抽象方法作为其实现的一部分。派生类则可以实现抽象方法,但这允许基类在执行此方法之前进行“某些特定处理”。

【讨论】:

  • ;这个解决方案非常适合后处理(第一个通用代码而不是派生类特定代码),但我需要相反:首先是派生类特定代码,然后是通用代码。
【解决方案3】:

我的建议是将基类分成两部分:一类是抽象类,一类是具体密封类。

例子

我假设你的基类看起来像这样:

public class BaseClass
{
    public void DoProcessing()
    {
        // this method must be overriden in each subclass
    }
}

让我们一分为二:

public abstract class BaseClass
{
    protected abstract DoProcessingImlementation();    

    public void DoProcessing()
    {
        // here you can add program logic or just call overridden implementation
        DoProcessingImplementation();
    }
}

public sealed class DefaultBaseClassImplementation : BaseClass
{
    public override DoProcessingImlementation()
    {
        // default implementation of method
    }
}

使用这种设计,如果您需要实现新的处理逻辑,则从BaseClass 继承新类,因为它是抽象的,您必须实现DoSomethigImplementation 方法。要访问默认处理逻辑,您应该使用DefaultBaseClassImplementation 类的实例。并且 DefaultBaseClassImplementation 被密封不会让你从错误的类继承。

【讨论】:

    猜你喜欢
    • 2014-07-10
    • 2012-02-25
    • 2015-02-23
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    相关资源
    最近更新 更多