5

如果我可以用抽象类做的所有事情都可以用普通的超类来做,那么当我可以使用普通的超类时,为什么还要使用抽象类呢?

4

3 回答 3

14

我认为评论和答案已经暗示了这一点,但我想更直白地说:你不能用普通的超类做所有你可以用抽象类做的事情。抽象类允许您定义方法的签名而不包括其实现,并且抽象类不允许您直接实例化它。

因此,如果我有 3 个方法的类签名并且我不想共享其中任何一个的实现,我将使用接口。如果我想共享其中一个方法的实现,我将使用一个抽象类,然后将该类中的两个方法设为抽象。如果我想共享方法的所有实现,我将使用抽象类,如果直接实例化它从来没有意义,或者我将使用常规类。

(这是基于我在 C# 方面的经验。不同语言的细节有所不同。)

于 2012-10-26T00:53:30.560 回答
1

当您需要以通用方式表示许多相似的事物时,抽象类非常有用。

例如,假设您想在代码中表示一个动物园,并且您需要获取杂货清单以确保您有正确的食物。你如何代表所有动物最喜欢的食物?各自发出什么噪音?他们如何移动呢?您可以尝试使用超类来保存食物、噪音和动作的大列表,但更容易为 Animal 定义一个通用定义,然后让每个动物提供自己的实现细节:

   public class Zoo {
      public Animals[] AnimalsInZoo { get; set;}

      public List<Food> GetGroceryList(){
         List<Food> groceries = new List<Food>();
         foreach(Animal a in Animals[]){
            groceries.Add(a.FavoriteFood);
         }
         return groceries;
      }

      public void  MakeAnimalsSing(){

         foreach(Animal a in Animals[]){
            a.MakeNoise();
         }

      }
   }

抽象的 Animal 类看起来像:

   public abstract class Animal {
      public abstract void MakeNoise();
      public abstract Food FavoriteFood { get; }
      public abstract void Move();
   }

并说动物园有两种动物:

   public class Panda : Animal{
      public override void MakeNoise(){
         // grunt
      }

      public override void Move(){
         // walk
      }

      public override Food FavoriteFood { 
         get {
              return new Bamboo();
         }
      }
   }  

      public class Parrot: Animal{
      public override void MakeNoise(){
         // talk
      }

      public override void Move(){
         // fly
      }

      public override Food FavoriteFood { 
         get {
              return new Cracker();
         }
      }
   }  

通过拥有一个通用的抽象类,我可以轻松地处理任意数量的不同动物类型,而无需明确知道我正在使用哪一种,但每种动物都可以以自己的方式行事。

超类无法提供那种灵活性或细节。

于 2012-10-26T00:55:01.740 回答
1

基类提供自己的方法实现。这些实现有时可以被覆盖(取决于语言)。

抽象类不提供默认实现,每个继承类都需要根据具体情况实现方法。

上述细节可能因语言而异。阅读相应的文档。

考虑这个例子:
一个Number抽象类有一个add()方法。AOddNumber和一个EvenNumber子类需要实现几乎相同的add()方法,所以那里有一些代码重复。在这里,拥有一个超类更有意义(或者,至少拥有一个 的RealNumber子类Number)。

但是,考虑Complex作为Number如果数字不是抽象的子类,add()在(假设它是实数加法算法)中找到的方法Number对复数没有意义。这里抽象类更有意义。某些语言允许您覆盖超类方法,但在这种情况下这有点尴尬。

于 2012-10-26T00:41:26.517 回答