在决定接口与抽象类时,正确的实现是什么?

时间:2017-11-25 17:48:18

标签: c# oop interface abstract-class

我最近遇到了与类创建/建模相关的问题。

模型动物王国为班级。使用您的类创建表示为虚拟动物园的各种对象。将20只动物添加到这个虚拟动物园(在你的程序的主要方法中,让每只动物发出声音。这不应该是20种不同的物种。)

我想到了这个问题并决定使用抽象类Animal而不是接口。然后我添加了两个类Bird,Mammal由Animal继承。

我的实施

  public abstract class Animal{

      abstract Sound MakeSound();
    }

    public class Bird : Animal
    {
       private Sound _sound;
       public Bird(Sound sound){
       _sound = sound;
    }
    public Sound MakeSound(){
          return _sound;
       }
    }
//same as above with Mammals

public class Program
{
  Animal crow = new Bird("Crow sound");
  Console.WriteLine(crow.MakeSound());

 Animal dog = new Mammal("Dog sound");
  Console.WriteLine(dog.MakeSound());

// and so on with other animals
}

我的问题是 -

  1. 我的实施有什么问题?
  2. 按照设计动物王国的正确方法是什么? oops概念?
  3. 在什么情况下我们使用接口而不是抽象类,反之亦然。 (用现实世界的例子)
  4. 请在网上找到一些可以解决这些问题的材料。 感谢。

2 个答案:

答案 0 :(得分:9)

首先,重要的是要认识到虽然"在阶级等级中塑造动物王国"是一个常见的初学者练习,常用于例子中 - 我在动画,哺乳动物,长颈鹿,老虎等等的例子中一直使用 - 使用OO技术解决它不是一个现实的问题。它只是想通过思考一个你已经理解的领域来让你思考面向对象编程中的概念。

拥有管理动物库存的软件的真实动物园并没有建立这样的阶级等级,因为它们的关注实际上并不包括哺乳动物对鸟类共有的共同点。尽管动物王国的类比对于使用OO很有用,但重要的是不要认为现实世界层次结构中存在的每个特征都必须在类层次结构中建模。

所以,那就是说,我的其余批评将假设你真的想把动物王国建模为锻炼。

其次,您实施的根本问题是层次结构要么不够深,要么太深。问题是哺乳动物和鸟类应该是抽象的因为世界上没有任何东西只是只是一只哺乳动物只是一只鸟。你想要的是一种抽象的类鸟,它可以扩展动物,然后是一种具体的(也可能是密封的)类型的Crow,它可以扩展Bird。

然后要问的问题是:我真的需要哺乳动物和鸟类的水平吗?他们对我的程序有用吗?我有没有一种方法可以接受任何哺乳动物,但没有蜥蜴?如果它没有用,那就消除它,直接从动物到乌鸦。

第三,乌鸦发出的声音是" caw caw"而不是"乌鸦声音"。 : - )

第四,回答你最好的问题:当你有几个不相关的东西时,你通常会使用一个界面。"可以做"同样的事情,但有不同的实现,你使用抽象类来共享实现细节的类,其中"是一种"关系。

发出声音是许多事情可以做的事情,彼此无关。鸟和钢琴不是同一种东西,它们有不同的机制,但它们都发出声音。因此,制作声音应该由界面表示。鸟是一种动物,所有动物都可能有鸟类专用的功能。

简而言之:鸟是一种动物,所以它应该是一个子类。鸟可以发出声音,还有许多其他东西也可以,所以发出声音应该是一个界面。

答案 1 :(得分:0)

您希望使用Interface的原因之一是C#不支持多重继承。

一般来说,我想将界面视为能力或特征而不是模型。

类似的东西:

    public interface ISwimable
    {
         int SwimmingSpeed { get; set; }
    }

    public interface IWalkable
    {
        int RunningSpeed { get; set; }
    }

现在,如果我有一种生活在水中的动物,我希望它能够实现ISwimable,如果我有一种可以行走的动物,它的类应该实现IWalkable,如果它可以同时实现,它将实现两者。 / p>