为什么C#允许没有抽象成员的抽象类?

C#规范第10.1.1.1节规定:

允许(但不是必需)抽象类来包含抽象成员。

这允许我创建这样的类:

public abstract class A { public void Main() { // it's full of logic! } } 

甚至更好:

 public abstract class A { public virtual void Main() { } } public abstract class B : A { public override sealed void Main() { // it's full of logic! } } 

这真是一个具体的课程; 它只是抽象的,因为人们无法实例化它。 例如,如果我想在B.Main()执行逻辑,我将首先得到B的实例,这是不可能的。

如果inheritance者实际上不必提供实现,那么为什么称它为抽象?

换句话说,为什么C#允许只有具体成员的抽象类?

我应该提一下,我已经熟悉了抽象类型和成员的预期function。

也许一个很好的例子是一个公共基类,它为派生类提供共享属性和其他成员,但不代表具体对象。 例如:

 public abstract class Pet { public string Name{get;set;} } public class Dog : Pet { public void Bark(){ ... } } 

所有宠物都有名字,但宠物本身就是一个抽象的概念。 宠物的实例必须是狗或其他种类的动物。

这里的不同之处在于,基类不是提供应该被实现者覆盖的方法,而是声明所有宠物至少由一个Name属性组成。

这个想法是强制实现者从类派生,因为它只是为一个可能更专业的实现提供基础。 因此,基类虽然没有任何抽象成员,但可能只包含核心方法,这些属性可以用作扩展的基础。

例如:

 public abstract class FourLeggedAnimal { public void Walk() { // most 4 legged animals walk the same (silly example, but it works) } public void Chew() { } } public class Dog : FourLeggedAnimal { public void Bark() { } } public class Cat : FourLeggedAnimal { public void Purr() { } } 

我认为对你的问题稍微准确一点的表述是:为什么C#允许只有具体成员的抽象类?

答案:没有充分的理由不这样做。 也许有人在那里有一些组织结构,他们喜欢在顶部有一个不可实例化的类,即使它下面的一个类只是inheritance并且什么都不添加。 没有充分的理由支持这一点。

你这么说 – 因为你无法实例化它; 它只是一个模板。

如果你声明它是抽象的,它不是“真正的具体类”。 作为设计选择,您可以使用它。

该设计选择可能与创建实体(具有混合术语的风险)实体对象的抽象以及可读性有关。 您可能希望声明Car类型的参数,但不希望将对象声明为Car – 您希望将Car类型的每个对象实例化为TruckSedanCoupeRoadsterCar要求inheritance者添加实现这一事实并没有降低其作为其inheritance者的抽象版本的价值,而这些版本本身无法实例化。

摘要意味着提供行为的抽象。 例如,Vehicle是一种抽象forms。 它没有任何真实世界的实例,但我们可以说Vehicle具有加速行为。 更具体地说,福特Ikon是一种车辆,雅马哈FZ是一种车辆。 这两者都有加速行为。

如果您现在以类forms进行此操作。 车辆是加速方法的抽象类。 虽然您可能/可能不会提供任何抽象方法。 但业务需求是车辆不应该被实例化。 因此,你把它抽象化。 另外两个类–Ikon和FZ是派生自Vehicle类的具体类。 这两个将有自己的属性和行为。

关于用法,在类声明上使用abstract但没有抽象成员与使用类public但在其构造函数上使用protected相同。 两者都强制派生类以便实例化它。

但是,就自我文档代码而言,通过标记类abstract它告诉其他人,即使它没有virtualabstract成员,该类也不会自己实例化。 而保护构造函数却没有这样的断言。

编译器不会阻止实现逻辑,但在你的情况下我只是省略抽象 ?! BTW可以用{ throw Exception("must inherit"); }实现一些方法{ throw Exception("must inherit"); } 并且编译器无法区分完全实现的类和函数,包括仅throw

这是一个潜在的原因:

图层超类型

图层中的所有对象都有不希望在整个系统中重复的方法,这种情况并不少见。 您可以将所有这些行为移动到公共的图层超类型中。

马丁福勒

没有理由阻止在抽象类中只有具体的方法 – 它只是不太常见。 Layer Supertype是一种可能有意义的情况。

我看到抽象类有两个主要目的:

  • 一个不完整的类,必须专门提供一些具体的服务。 在这里,抽象成员是可选的 。 该类将提供子类可以使用的一些服务,并且可以定义它用于提供其服务的抽象成员,就像在模板方法模式中一样 。 这种类型的抽象类旨在创建inheritance层次结构

  • 仅提供静态实用程序方法的类 。 在这种情况下,抽象成员根本没有意义。 C#支持静态类的概念,它们是隐式抽象和密封的。 这也可以通过带有私有构造函数的密封类来实现。