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

本文关键字:什么 区别 抽象类 基类 简单 | 更新日期: 2023-09-27 18:32:12

我正在做一种研发,对抽象类的概念感到困惑。

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

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

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

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

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

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

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

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

还要考虑一个没有抽象的世界中的非空方法。 他们需要投掷(即 NotImplementedException ) 或返回无效值(即 null )。 这可能比什么都不做的方法要糟糕得多。

主要区别在于编译器不允许您实例化抽象类,而您可以实例化基类(这可能没有意义)。

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定义,并且它会做一些事情。

有些类在现实世界中根本不存在,因此在概念上应该标记为abstract。例如,考虑abstract class Animal .在现实世界中没有所谓的"动物"。相反,有具体类型的动物,如DogCat等。

一个简单的

答案可能是:-

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

抽象类具有类方法的声明。 任何继承抽象类的类都必须实现它的抽象方法,否则就会抽象化自己。不能实例化抽象类

例:-

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 中实现才能使用它。