I'm having problems understanding the difference between the use of Interfaces and abstract classes.
For example, please see the following UML diagramm:
What is the difference between these two?
I'm having problems understanding the difference between the use of Interfaces and abstract classes.
For example, please see the following UML diagramm:
What is the difference between these two?
I'll provide an explanation with code and a shorter explanation. If you don't want to read, just skip to the "plain English explanation" below.
In C++ terms an abstract class is a class which implement some methods but don't implement other methods. That means: you can use some of their methods, but you'll have to implement the non-implemented ones.
Interfaces are pure classes in C++, that is, a class which doesn't implement anything and you must implement everything if you want your class to be conformant to that interface.
E.g. - try this out with the link below
#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;
}
If you want the over-simplified version:
Interfaces are usually "contracts" which you need to adhere in toto: you need to agree with everything and implement everything or it doesn't work.
Abstract classes are partial-contracts, there are some things which you must agree/implement, but there's also some other stuff which is already there and you can choose whether to re-implement it (override) or just be lazy and use the existing ones.
Abstract classes used for dealing with code duplication between subclasses, because they can share common logic and data. Interfaces just define common contract of implementors.
So, if there is no common implementation to share, then use interface (I always start with interface). If some common implementation will appear, then extract abstract base class and move common code there. But even in this case I keep interface in hierarchy, because it's easy to mock and it is more abstract, which allows other classes not depend on any implementation at all.
In your case I think Circle
and HalfCircle
share some implementation. So I would go with moving common code to Circle
and inheriting HalfCircle
from itЖ
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; }
}
}
If all shapes share some data or logic for calculating area, then it makes sense to declare base abstract Shape
class for this common code. But if you will look at area calculation of square, there is nothing common with circle:
public class Square : IShape
{
public double Side { get; set; }
public double Area
{
get { return Side * Side; }
}
}
So IShape
interface would be enough, because classes share only contract:
public interface IShape
{
double Area { get; }
}
An inheritance relationship, potentially using an abstract class, can usually be described as 'is a' and the implementation of an interface is a 'can be'. This concept can help when choosing which to use.
So if a Square 'is a' shape then inheritance would be an acceptable way of modelling this relationship.
Furthermore, an abstract class will give you the ability to provide common features. Where as an interface cannot contain any implementation.