在C#中使用’抽象覆盖’有什么用?

What is the use of 'abstract override' in C#?

出于好奇,我尝试重写基类中的抽象方法,并使用方法实现抽象。如下:

1
2
3
4
5
6
7
8
9
10
public abstract class FirstAbstract
{
    public abstract void SomeMethod();
}

public abstract class SecondAbstract : FirstAbstract
{
    public abstract override void SomeMethod();
    //?? what sense does this make? no implementaion would anyway force the derived classes to implement abstract method?
}

想知道为什么C编译器允许写"抽象重写"。这不是多余的吗?应该是一个编译时错误来执行类似的操作。它是否适用于某些用例?

谢谢你的关心。


在MicrosoftDocs上有一个很有用的例子——基本上你可以强制派生类为一个方法提供一个新的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class D
{
    public virtual void DoWork(int i)
    {
        // Original implementation.
    }
}

public abstract class E : D
{
    public abstract override void DoWork(int i);
}

public class F : E
{
    public override void DoWork(int i)
    {
        // New implementation.
    }
}

If a virtual method is declared abstract, it is still virtual to any
class inheriting from the abstract class. A class inheriting an
abstract method cannot access the original implementation of the
method—in the previous example, DoWork on class F cannot call DoWork
on class D. In this way, an abstract class can force derived classes
to provide new method implementations for virtual methods.


我发现它对于确保派生类中正确的ToString()实现非常有用。假设您有抽象的基类,并且您真的希望所有派生类都定义卑鄙的ToString()实现,因为您正在积极地使用它。你可以用abstract override非常优雅地完成它:

1
2
3
4
public abstract class Base
{
    public abstract override string ToString();
}

对于实现人员来说,这是一个明确的信号,即ToString()将以某种方式(如将输出写入用户)用于基类。通常,他们不会考虑定义这个覆盖。


有趣的是,C编译器的Roslyn版本中有一个抽象的重写方法,我觉得这很奇怪,可以写一篇关于以下内容的文章:

Strange but legal


假设SecondAbstract处于三类层次结构的中间,它希望从其基础FirstAbstract实现一些抽象方法,而将其他方法x留给它的子ThirdAbstract实现。

在这种情况下,由于SecondAbstract不想提供一个实现,因此它被迫用abstract来修饰方法x;同时,由于它没有定义一个新的方法x,而是想把实现x的责任转移到它的子项,所以它也被迫用override来修饰方法x。因此,abstract override

一般来说,由abstractoverride建模的概念是正交的。第一种方法强制派生类实现方法,而第二种方法识别出方法与在基类上指定的方法相同,而不是new方法。

因此:

  • 两者都不是关键字:"简单"方法
  • 仅限abstract:派生类必须实现
  • 仅限override:基类中定义的方法的实现
  • abstract override:派生类必须实现在基类中定义的方法


这种设计模式称为模板方法模式。

关于模板方法的维基百科页面

一个简单的、非软件的例子:有很多军事单位:坦克、喷气机、士兵、战舰等。他们都需要实现一些通用的方法,但他们将以非常不同的方式实现这些方法:

  • MOVEL()
  • 攻击()
  • 后退()
  • REST()

等。。。


如果在SecondAbstract中没有将SomeMethod声明为abstract override,编译器会期望该类包含该方法的实现。对于abstract override来说,很明显,实现应该在派生自SecondAbstract的类中,而不是在SecondAbstract本身中。

希望这有帮助…


这样做是因为在子类中,不能使用与基类中同名的abstract方法。override告诉编译器您正在重写基类的行为。

希望这就是你要找的。