简单基类和抽象类有什么区别?

时间:2013-09-19 17:15:09

标签: c# .net abstract-class base-class

我做了一种R& D,并且对抽象类的概念感到困惑。

我对抽象类的了解是它可能包含具体的方法,它可能包含虚方法。它可能包含也可能不包含抽象方法,它可能包含字段并限制直接创建实例。

但是我们可以在一个简单的基类中实现所有这些(虚拟方法的添加会做很多事情,因为具有虚拟方法的基类不包含实现,并且覆盖与抽象方法相同)。那么为什么我们需要一个抽象类,虽然接口支持多继承和事件?

4 个答案:

答案 0 :(得分:14)

  

但我们可以在一个简单的基类中实现所有这些

不,你不能。您不能拥有一个具有抽象方法的非抽象类(定义了签名的方法,但没有给出实现,因此强制派生类提供实现)。

抽象类存在,以便它们可以提供已实现方法和抽象方法的组合。

您可以尝试通过使用不执行任何操作的具体实现来避免使用abstract类,但它有许多缺点:

  • 它不会强制调用者覆盖实现。
  • 它给人的印象是,特别是类型和那些方法是有效的,而事实上它们并非如此。通过添加抽象方法和类型的功能,可以防止意外使用不完整类型的人意识到它不完整。
  • 它为子类提供了一个明确的合同,即它们需要提供什么功能,以及基类的哪些方法正在工作,但可以选择扩展。

在没有抽象的世界中也考虑非空方法。他们需要抛出(即NotImplementedException)或返回无效值(即null)。这可能比一无所获的方法要糟糕得多。

答案 1 :(得分:7)

主要区别在于编译器不会让你实例化一个抽象类,而你可以实例化一个基类(这可能没有意义)。

AbstractType a = new AbstractType(); //compiler error
AbstractType d = new DerivedType(); //OK

BaseType b = new BaseType(); //OK

注意变量d我们保证抽象方法已被覆盖(否则DerivedType类会产生编译错误。)

既然你正在评论很多混乱,我会给你一个我真正让这个概念点击给我的例子。想象一下,你正在制作塔防游戏。你有一个塔级,每个塔都有攻击能力,所以你要做一个像这样的抽象塔类:

abstract class Tower
{
    abstract void Attack();
}

现在我可以制作几个塔类:

class FlameTower : Tower
{
    override void Attack()
    {
        //Shoot flames at everyone
    }
}

class IceTower : Tower
{
    override void Attack()
    {
        //Shoot ice everywhere
    }
}

现在,如果您要申报塔楼列表,可以写下:

 List<Tower> towerList = new List<Tower>();
 towerList.Add(new FireTower());
 towerList.Add(new IceTower());

然后遍历它们并使它们全部受到攻击:

 foreach (Tower t in towerList)
 {
     t.Attack();
 }

每个类都保证已经实现了攻击,因为它被标记为抽象,如果没有,则会出现编译错误。现在所有这些都可以用基类来完成,除了基类允许这样做:

 towerList.Add(new Tower());

现在,当它试图对new Tower()进行攻击时,它会触及一个空白的抽象方法,这不是我们想要的。因此,为了禁止将某些东西声明为通用塔,我们将该类抽象化,然后我们知道所有内容都将拥有它自己对Attack的定义,它会做一些事情。

答案 2 :(得分:2)

一个简单的答案可能是: -

基类有自己的方法实现,这些实现可以在继承的类中使用/添加。您可以实例化基类

抽象类具有类方法的声明。任何继承抽象类的类都必须实现它的抽象方法,或者变成抽象自己。您无法实例化抽象类

示例: -

public abstract class A
{
   public void Method1()
   {
     //method code
   }

   public abstract void Method2();

   public virtual void Method3()
   {
    //method code for class A, when class A calls Method3, this code is executed
   }
}

public class B : A
{
   public override void Method2()
   {
     //this must be implemented here to use it
   }

   public override void Method3()
   {
     //method code for class B, when class B calls Method3, this code is executed
     //or, if you choose not to override this method, the compiler will use the code in class A
   }
}

B类仍然可以使用A类中的Method1,因为它是继承的。如果A类是抽象的,那么所有方法都将被声明为Method2,并且必须在B类中实现,以便可以使用它。

答案 3 :(得分:2)

有些类在现实世界中不存在,因此在概念上应标记为abstract。例如,考虑abstract class Animal。现实世界中没有“动物”这样的东西。相反,有一些具体类型的动物,如DogCat等。