在C#中使用“抽象覆盖”是什么?
出于好奇,我试图覆盖基类中的抽象方法,并且实现抽象方法。 如下:
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#编译器允许编写“抽象覆盖”。 这不是多余的吗? 应该是编译时错误做这样的事情。 它是否适用于某些用例?
感谢您的关注。
在MSDN上有一个有用的例子 – 基本上你可以强制派生类为方法提供一个新的实现。
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. } }
如果一个虚拟方法被声明为抽象的,那么对于从抽象类inheritance的任何类都是虚拟的。 inheritance抽象方法的类不能访问方法的原始实现 – 在前面的例子中,类F上的DoWork不能调用类D上的DoWork。 通过这种方式,抽象类可以强制派生类为虚拟方法提供新的方法实现 。
我发现确保派生类中正确的ToString()
实现非常有用。 假设您有抽象基类,并且您确实希望所有派生类都定义有意义的ToString()
实现,因为您正在使用它。 你可以用abstract override
非常优雅的做到这一点:
public abstract class Base { public abstract override string ToString(); }
这对于实现者来说是一个明确的信号, ToString()
将以某种方式在基类中使用(比如将输出写入用户)。 通常情况下,他们不会考虑定义这个覆盖。
有趣的是,C#编译器的Roslyn版本在其中有一个抽象的重写方法,我发现它足够奇怪的写一篇文章:
假设SecondAbstract
处于三级层次结构的中间,并且希望从其基础FirstAbstract
实现一些抽象方法,而将其他方法X从其子ThirdAbstract
。
在这种情况下, SecondAbstract
被迫用abstract
来装饰方法X,因为它不想提供一个实现; 同时,由于它不是定义一个新的方法X,而是强制要用override
来装饰它,而是要把执行X的责任移到它的子节点。 因此, abstract override
。
一般来说, abstract
和override
build模的概念是正交的。 第一个派生类实现一个方法,而第二个派生类认识到一个方法和基类中指定的相同,而不是new
。
因此:
- 既不关键字:“简单”的方法
- 仅
abstract
:派生类必须实现 - 仅
override
:在基类中定义的方法的实现 -
abstract override
:派生类必须实现在基类中定义的方法
这是因为在子类中你不能有与基类相同的名字的abstract
方法。 override
告诉编译器,你正在重写基类的行为。
希望这是你在找什么。
如果您没有在SecondAbstract
声明SomeMethod
为abstract override
,那么编译器会期望该类包含方法的实现。 有了abstract override
,很明显,实现应该在从SecondAbstract
派生的类中,而不是在SecondAbstract
本身中。
希望这可以帮助…
这种devise模式被称为模板方法模式。
维基百科页面模板方法
一个简单的非软件示例:有一大堆军事单位:坦克,喷气机,士兵,战列舰等等。他们都需要实施一些常用的方法,但是他们会以不同的方式实施:
- 移动()
- 攻击()
- 撤退()
- rest()
等等…