5

有这样的东西:

public abstract class AAA
{
  protected abstract virtual string ToString()    // Error
  {
    // Base Stuff
  }
}

public abstract class BBB : AAA
{
  public override string ToString()
  {
    // Use base.ToString();
    // More Stuff
  }
}

我读了另一篇文章(虚拟类中的抽象方法),女巫很像我的问题,但有一点不同。我希望 AAA.ToString() 具有基本行为强制派生类覆盖它。

我知道我可以做这样的事情(向下滚动),但我正在寻找合适的方法。

public abstract class AAA
{
  public abstract string ToString();
  protected string ToString2()
  {
    // Base Stuff
  }
}

public class BBB : AAA
{
  public override string ToString()
  {
    // Use base.ToString2();
    // More Stuff
  }
}

我也可以制作一个 IAAA 界面并构建我的 BBB 类,例如

public class BBB : AAA, IAAA { ... }

但在我看来不对。

4

3 回答 3

5

您的方法本质上是正确的方法...

编辑:

您的“规格”是:

  1. 默认行为
  2. 必需的覆盖

现在,由于您似乎希望始终执行“默认行为”,因此您需要

public string ToString()
{
    // placeholder for some default behaviour

    string result = doToString();

    // placeholder for some more default behaviour

    return result;
}

protected abstract string doToString();

这仅在您知道基类一般在做什么并且想要doToString()在派生类中提供实现的情况下才有效。这被称为模板方法设计模式。

但是,如果您正在寻找一种方法来要求派生类的实现者调用base.ToString()它的实现ToString(),那么就没有办法做到这一点。通过允许覆盖,您可以让派生类控制其实现。

您可以记录您的建议以始终调用base.ToString(),但仅此而已。

使用接口为您的类定义公共契约。与模板方法模式相比,这不会给您带来任何额外的好处,因为您仍然需要从基类派生以获得“默认”实现。

您是否有任何关于您尝试在基类中提供的“默认行为”的详细信息?也许这将有助于找到更好的解决方案。查看引用的问题,这基本上是相同的方法。

于 2009-08-25T02:46:18.653 回答
2

我刚刚发现如何获得我想要的行为:

public abstract class AAA
{
  protected abstract string ToStringSpecific();
  protected string ToString()
  {
    // Base Stuff
    ...
    // Use this.ToStringSpecific();
  }
}

public class BBB : AAA
{
  protected override string ToStringSpecific()
  {
    // Specific Stuff
  }
}
于 2009-08-26T00:41:50.363 回答
0

不,不可能将当前的虚函数变成抽象函数。正如您所建议的,执行此操作的唯一方法是创建另一个抽象的函数。这可以说是一种更合适的方法(我同意这一点)。

于 2009-08-25T02:47:07.590 回答