出于好奇,我尝试覆盖基类中的抽象方法,并实现抽象方法。如下:
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#编译器允许编写'抽象覆盖'。这不是多余的吗?应该是一个编译时错误来做这样的事情。是否适用于某些用例?
谢谢你的关注。
在Microsoft Docs上有一个有用的例子 - 基本上你可以强制派生类为方法提供一个新的实现。
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.
}
}
如果将虚方法声明为abstract,则它对于从抽象类继承的任何类仍然是虚拟的。继承抽象方法的类无法访问方法的原始实现 - 在前面的示例中,类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,因为它不想提供实现;与此同时,它被迫用override
来装饰它,因为它没有定义一个新的方法X,但是想要将实现X的责任转移给它的孩子。因此,abstract override
。
通常,由abstract
和override
建模的概念是正交的。第一个强制派生类来实现一个方法,而第二个派生承认一个方法与基类上指定的方法相同而不是new
。
因此:
abstract
:派生类必须实现override
:基类中定义的方法的实现abstract override
:派生类必须实现基类中定义的方法这样做是因为在子类中,您不能使用与基类同名的abstract
方法。 override
告诉编译器你正在覆盖基类的行为。
希望这是你正在寻找的。
如果你没有在SomeMethod
中将abstract override
声明为SecondAbstract
,编译器会希望该类包含该方法的实现。使用abstract override
很明显,实现应该是从SecondAbstract
派生的类,而不是SecondAbstract
本身。
希望这可以帮助...
此设计模式称为模板方法模式。
Wikipedia page on Template Methods
一个简单的,非软件的例子:有一堆军事单位:坦克,喷气式飞机,士兵,战列舰等。他们都需要实施一些常用的方法,但他们将以非常不同的方式实施它们:
等等...