接口与抽象类或一般的多态

时间:2014-02-07 09:39:31

标签: oop interface abstract-class

我在理解使用Interfaces和抽象类之间的区别时遇到了问题。

例如,请参阅以下UML图表:

Interfaces vs. Abstract Classes

这两者有什么区别?

3 个答案:

答案 0 :(得分:4)

我将提供代码解释和更简短的解释。如果您不想阅读,请跳到下面的“简明英语解释”。


代码

的说明
  • 在C ++术语中,抽象类是实现某些方法的类,但不实现其他方法。这意味着:您可以使用他们的一些方法,但您必须实现未实现的方法。

  • 接口在C ++中是纯类,也就是说,一个没有实现任何东西的类,而如果你希望你的类符合该接口,你必须实现所有东西

E.g。 - 使用下面的链接试试这个

#include <iostream>
using namespace std;

// Shape is abstract class: some methods are already available, some are not
class Shape
{
public:
  // This is already implemented and ready for polymorphism
  virtual void area() { cout<<"Shape area"<<endl;}
  // You MUST implement this
  virtual void implement_me() = 0;
};

class Circle : public Shape
{
public:
  virtual void area() { cout<<"Circle area"<<endl;}
  void implement_me() { cout<<"I implemented it just because I had to"<<endl;}
};

class HalfCircle : public Circle
{
public:
  virtual void area() { cout<<"HalfCircle area"<<endl;}
};


// ShapeInterface is a pure class or interface: everything must be implemented!
class ShapeInterface
{
public:
  virtual void area() = 0;
};

class CircleFromInterface : public ShapeInterface
{
public:
  // You MUST implement this!
  virtual void area() { cout<<"CircleFromInterface area from interface"<<endl;};
};



int main() {

    Shape* ptr_to_base = new HalfCircle();
    ptr_to_base->area(); // HalfCircle area, polymorphism
    ptr_to_base->Shape::area(); // Shape area
    ptr_to_base->implement_me(); // from Circle


    ShapeInterface *ptr_to_base_int = new CircleFromInterface();
    ptr_to_base_int->area(); // Just the derived has it

    return 0;
}

http://ideone.com/VJKuZx


普通英语解释

如果您想要过度简化的版本:

  • 接口通常是“合同”,您需要坚持完全:您需要同意所有内容并实施所有内容或不起作用。

  • 抽象类是部分合同,有些事情你必须同意/实施,但也有一些已经存在的其他东西你可以选择是否重新实施它(覆盖)或只是懒惰并使用现有的。

答案 1 :(得分:2)

用于处理子类之间代码重复的抽象类,因为它们可以共享公共逻辑和数据。接口只定义了实现者的通用契约。

因此,如果没有共享的通用实现,那么使用接口(我总是从接口开始)。如果出现一些常见的实现,则提取抽象基类并在那里移动公共代码。但即使在这种情况下,我仍然将接口保持在层次结构中,因为它很容易被模拟,而且它更抽象,这使得其他类可以完全不依赖于任何实现。


在您的情况下,我认为CircleHalfCircle分享了一些实现。所以我会将公共代码移到Circle并从itЖ继承HalfCircle

public class Circle : IShape
{
    public double Radius { get; set; }
    public virtual double Area
    {
        get { return Math.PI * Radius * Radius; }
    }
}

public class HalfCircle : Circle
{
    public override double Area
    {
        get { return base.Area / 2; }
    }
}

如果所有形状共享一些用于计算区域的数据或逻辑,则为此公共代码声明基本抽象Shape类是有意义的。但是如果你看一下square的面积计算,那么圆圈就没有什么共同之处了:

public class Square : IShape
{
    public double Side { get; set; }

    public double Area
    {
        get { return Side * Side; }
    }
}

所以IShape接口就够了,因为类只共享契约:

public interface IShape
{
    double Area { get; }
}

答案 2 :(得分:0)

可能使用抽象类的继承关系通常可以描述为“是a”,接口的实现是“可以”。这个概念在选择使用哪个时可以提供帮助。

因此,如果Square'是'shape',那么继承将是建立这种关系的可接受方式。

此外,抽象类将使您能够提供常用功能。其中一个接口不能包含任何实现。