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

时间:2010-06-08 18:00:27

标签: c# language-design abstract

C#规范section 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的实例,这是不可能的。

如果继承人实际上不必提供实现,那么为什么要将其称为抽象?

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

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

9 个答案:

答案 0 :(得分:23)

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

public abstract class Pet
{
    public string Name{get;set;}
}

public class Dog : Pet
{
    public void Bark(){ ... }
}

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

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

答案 1 :(得分:11)

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

例如:

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()
    {
    }
}

答案 2 :(得分:8)

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

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

答案 3 :(得分:3)

你说过 - 因为你无法实例化它;它只是一个模板。

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

该设计选择可能与创建实体(具有混合术语的风险)抽象现实世界对象的实体有关,并具有可读性。您可能希望声明类型Car的参数,但不希望将对象声明为Car - 您希望将Car类型的每个对象实例化为{{1} },TruckSedanCoupeRoadster要求继承者添加实现的事实并没有减损它作为其本身无法实例化的继承者的抽象版本的价值。

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

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

但是,就自我文档代码而言,通过标记类abstract,它会通知其他人,即使它没有virtual,或者它本身也不会被实例化。 abstract个成员。而保护构造函数却没有这样的主张。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

这是一个潜在的原因:

Layer Supertype

  

所有对象并不罕见   在一个图层中有你没有的方法   想要在整个过程中重复   系统。你可以移动所有这些   行为进入一个共同的层   超类型。

     

- Martin Fowler

没有理由阻止在抽象类中只有具体的方法 - 它不常见。 图层超类型是一种可能有意义的情况。

答案 8 :(得分:0)

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

  • 一个不完整的类,必须专门提供一些具体的服务。这里,抽象成员将是可选。该类将提供子类可以使用的一些服务,并可以定义它用于提供其服务的抽象成员,如Template Method Pattern中所示。此类抽象类旨在创建继承层次结构

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