Interfaces or Abstract Classes?

How do you choose between interface and abstract class?

I have been asking this question in interview for some years now. I get to hear lot of interesting answers from folks. And these answers have helped me make great addition to my knowledge. If you google this topic you would find lot of interesting articles. This article on MSDN offers a good discussion on the topic. To summarise the recommendations from there and few other articles I came across, here are the reasons in favour of abstract classes

  1. Use abstract class if you have a default implementation of some behavior that child classes do not have to implement
  2. Prefer abstract classes if your contract has possibility of changing over time. So if you are using abstract classes and you needed add a new method to your abstract class, you can happily add that without breaking any code using that class. Same is not true for interfaces.

And these are the reasons in favour of interfaces

  1. Since multiple inheritance is not supported in C#, you cannot inherit your class from two abstract classes. Interface is your only option in such situations.
  2. If there is no default or common behavior among all the classes that are inheriting from abstract class then interface may bea better choice.

Somehow I do not feel confident that these give a complete picture

What is wrong with this?

First, above recommendations are mostly around syntax a particular language supports and not around semantics (e.g. use interfaces if you need multiple inheritance). By semantics I mean, what definition of an interface fundamentally differentiates it from abstract class?

Second, I feel the above criteria are too futuristic. By that I mean, they all depend on you knowing how your design is going to take shape in future. At times, I may have some idea of how my design is going to take shape in future but most of the times I do not have enough clarity to know in advance

  1. Whether I am going to need to inherit from multiple abstract classes or not
  2. Whether there is going to be a default implementation of some contract or not
  3. Whether I would add a new method to a contract or define a new contract entirely in order to implement a change

So, if you do not know which way your software is going to go, there is no way you can base your decision of interface or abstract class on these reasons.

So what is the option?

Lately, I have using below heuristic to determine when to use interfaces/abstract classes and I feel quite excited about it as it works most of the time.

Interfaces represent capabilities and abstract classes represent type

in other words

Implementing interfaces represent can-do relationship and inheriting from (abstract) class represents an is-a relationship

To elaborate this point, let's consider following two classes

public class Camera  
{
    public void Shoot()
    {
        //Take a picture here
    }
}

public class Gun  
{
    public void Shoot()
    {
        //Hit the target
    }
}

Both Camera and Gun can Shoot, that is their capability. But they are both not the same type of things, they are completely different. So an interface like below would make more sense here

public interface IShootable  
{
    void Shoot();
}

public class Camera : IShootable  
{
    public void Shoot()
    {
        //Take a picture here
    }
}

public class Gun : IShootable  
{
    public void Shoot()
    {
        //Hit the target
    }
}

If you have learned OO programming the same way I did, then you would remember the classic shape example as below

public abstract class Shape  
{
    void Draw();
}

public class Rectangle : Shape  
{
    public void Draw()
    {
        //Draw a rectangle here
    }
}

public class Circle : Shape  
{
    public void Draw()
    {
        //Draw a circle here
    }
}

Rectangle and Circle inheriting from Shape makes perfect sense here becaue Rectangle/Circle are a type of Shape.

In closing

As your software grows and new features start poring in, old features keep changing, you would hit a point where you would say to yourself God, I should not have used an abstract class there. I think at that point, all the reasonings I mentioned in the beginning of this post come handy.

Suhas Chatekar

Discussion

  • Comment with Disqus
  • Comment with Facebook
comments powered by Disqus