The answer depends of some factors like common behaviors and level of extensibility. I'm going to explain it creating here an imaginary concept of social network so for us a social network is something that can post messages with images and save an history of posted messages. Then our social networks will share behavior so I will create a base class (abstract class).
public abstract class SocialNetwork
{
public List<string> History { get; private set; }
protected SocialNetwork()
{
History = new List<string>();
}
public void Post(string comment, byte[] image)
{
DoPost(comment, image);
History.Add(comment);
}
protected virtual void DoPost(string comment, byte[] image)
{
}
}
Now I will create our social networks: facebook and twitter
public class Facebook : SocialNetwork
{
protected override void DoPost(string comment, byte[] image)
{
//Logic to do a facebook post
}
}
public class Twitter : SocialNetwork
{
protected override void DoPost(string comment, byte[] image)
{
//Logic to do a twitter post
}
}
Everything look fine until now. Well, imagine we have to handle a totally different kind of social network, for instance some social network that not store messages history, something like Snapchat:
public class Snapchat : SocialNetwork
{
private string _lastMessage;
protected override void DoPost(string comment, byte[] image)
{
//Logic to do a snapchat post
_lastMessage = comment;
ProcessLastMessage();
History.Clear();
}
private void ProcessLastMessage()
{
//Some logic here.
}
}
As you can note above the Snapchat class inherits from SocialNetwork class so Snapchat class will store a history of posts too. But we don’t want it so we have to put code to clear the history list.
Interfaces comes in action
The problem with the implementation above is Snapchat have a thing he don’t need i.e the History so we need a higher level of abstraction here, SocialNetwork base class is what we know how a normal social network, but we need a super abstraction to define what a SocialNetwork do without define any behavior for it so we need define an interface.
public interface ISocialNetwork
{
void Post(string message, byte[] image);
}
Now we will do SocialNetwork class to implement ISocialNetwork:
public abstract class SocialNetwork : ISocialNetwork
{
...
public void Post(string comment, byte[] image)
{
...
}
...
}
Now here is the new Snapchat class:
public class Snapchat : ISocialNetwork
{
private string _lastMessage;
public void Post(string message, byte[] image)
{
//Logic to do a snapchat post
_lastMessage = message;
ProcessLastMessage();
}
private void ProcessLastMessage()
{
//Some logic here.
}
}
Now the design is powerfull enough. Facebook and Twitter share common behavior from SocialNetwork (abstract class) and it implements ISocialNetwork (interface). Snapchat class not share any behavior with Facebook and Twitter but it is a social network too so it implements directly ISocialNetwork interface.
You can read the full article from here: http://www.theagilethinker.com/2015/08/22/an-interesting-example-of-convivence-between-abstract-classes-and-interfaces/