【问题标题】:Override abstract method, but keep method abstract?覆盖抽象方法,但保持方法抽象?
【发布时间】:2013-09-12 11:21:42
【问题描述】:

我想重写一个抽象方法,但要保持它是抽象的,所以派生类需要自己实现它。

public abstract class ComponentController
{
    public abstract void CreateCustomColumns();
}

public abstract class ClientComponentController : ComponentController
{
    public override void CreateCustomColumns()
    {
        // All grids to do with clients should show these columns.
        Grid.AddColumn("Client" ...
        Grid.AddColumn("ClientLocation" ...
        Grid.AddColumn("ClientPhoto" ...
    }
}

public class ClientInvoicesComponentController : ClientComponentController
{
    public override void CreateCustomColumns()
    {
        base.CreateCustomColumns();
        // On top of the generic columns, I also want to show these.
        Grid.AddColumn("InvoiceNumber" ...
        Grid.AddColumn("InvoiceDate" ...
    }
}

public class ClientCommunicationsComponentController : ClientComponentController
{
    public override void CreateCustomColumns()
    {
        base.CreateCustomColumns();
        // On top of the generic columns, I also want to show these.
        Grid.AddColumn("CommunicationDate" ...
        Grid.AddColumn("CommunicationType" ...
    }
}    

在此代码中,ClientInvoicesComponentController 不需要实现 CreateCustomColumns(),因为这是不允许的:

public abstract class ClientComponentController : ComponentController
{
    public abstract override void CreateCustomColumns()
    {
        Grid.AddColumn("Client" ...
        Grid.AddColumn("ClientLocation" ...
        Grid.AddColumn("ClientPhoto" ...
    }
}

--> "Abstract method cannot declare a body"

那么,如何在 ClientComponentController 中覆盖 CreateCustomColumns(),但仍然强制在 ClientInvoicesComponentController 等派生类中再次覆盖它?

当然它仍然可以被覆盖,但是没有任何东西可以向开发者表明它必须被覆盖......这是我的目标。

-布伦丹

【问题讨论】:

  • 我发誓这个问题是不久前被问到的。 Aaanyways:这是不可能的,只是让你的共享实现一个不同的方法,或者使用模板方法模式。显然,如果没有人可以直接调用实现 B.A(),那么重写 public abstract 方法是没有意义的。
  • 如果您稍微解释一下您正在尝试做什么,这可能会有所帮助。从这里看起来您正试图在 B 类中提供一个 半实现 ,派生类必须覆盖该类,但可以选择是否使用基类,恕我直言,这很令人困惑。看到一个用例真的很有帮助。
  • 如果有帮助,我已将用例添加到帖子中。
  • @BrendanHill Near 据我所知,将ClientComponentController 的实现移动到非抽象保护方法不会解决任何问题。我也看不出覆盖需要调用基本方法的太多原因 - 似乎您的设计是覆盖类 add 新列到网格,所以你不妨只是始终从构造函数调用基本实现。
  • @BrendanHill 如果您希望覆盖类能够控制是否添加基类的列,您始终可以公开列定义的集合并使此操作显式而不是让它成为继承链的产物。

标签: c# oop overriding abstract


【解决方案1】:

一句话:不是。

抽象的方法意味着它被声明但未定义。在这种情况下,被定义但抽象并没有真正的意义,所以这是不可能的。

我也非常想知道您的用例。如果您希望子类继承某些行为,但还要添加它们自己的功能,您可以这样:

public abstract class BaseClass
{
    public void DoSomething()
    {
        // Base class behaviour goes here.
        DoSomethingInternal();
    }

    protected abstract void DoSomethingInternal();
}

public class SubClass : BaseClass
{
    protected override void DoSomethingInternal()
    {
        // Sub class behaviour goes here.
    }
}

【讨论】:

  • 谢谢 Jan,我也很怀疑。如果您有任何进一步的想法,我已经用一个用例 FYI 更新了帖子。
【解决方案2】:

在这种情况下,我认为最好将您的逻辑分为两种方法,一种是您使用的方法,另一种是您的用户使用的方法。假设“CreateCustomColumns”方法是您希望用户覆盖的名称,您可以为自己创建另一个方法,例如“CreateCustomColumnsCore”。这些类可能如下所示:

public abstract class ComponentController
{
    protected abstract void CreateCustomColumnsCore();
}

public abstract class ClientComponentController : ComponentController
{
    protected override void CreateCustomColumnsCore()
    {
        // your code here

        CreateCustomColumns();  // call users' implementation
    }

    public abstract void CreateCustomColumns();
}

public class ClientInvoicesComponentController: ClientComponentController
{
    public override void CreateCustomColumns()
    {
        // user must implement this method.
    }
}

用户仍然可以覆盖您的 CreateCustomColumnsCore 方法,这可能是一个功能或错误,取决于您是否允许用户这样做。

【讨论】:

  • 感谢 Ricky,不幸的是,有“事件序列”问题阻止了这种选择,即。 CreateCustomColumns() 必须作为序列中的特定点触发,而不是构造函数。
  • 抱歉,该评论是针对上述回复的。您建议的选项也可以工作,除了许多类从基本 ComponentController 继承并直接覆盖 CreateCustomColumns() 。这种解决方案会在需要覆盖的区域之间带来不一致。
  • 感谢 Ricky - 我最终接受了您的建议,并接受了整个程序中的细微不一致。
  • 我不认为这有点不一致。在您的情况下,这两种方法用于 2 个不同的目的。或者,您可以保持方法名称一致,但您需要让您的用户不要忘记调用您的基本方法。我不确定是否有第二个更好的选择。
  • 另一方面,我不认为你真的需要强迫你的用户调用你的基本方法,因为他们必须这样做,否则你的用户不会得到正确的输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 2014-03-18
  • 1970-01-01
相关资源
最近更新 更多