This took me a while to wrap my head around this and ultimately I just had to write code that utilized both to figure it out.
An abstract class is an inheritance based concept. It should satisfy the "is a" rule (checkout
Liskov Substitution Principle). As an example:
- public abstract class Dog
-
{
-
public abstract void Bark();
-
}
-
-
public class Bulldog
-
: Dog
-
{
-
public override void Bark()
-
{
-
Console.WriteLine("Woof");
-
}
-
}
-
-
public class Chihuahua
-
: Dog
-
{
-
public override void Bark()
-
{
-
Console.WriteLine("yip");
-
}
-
}
-
A bulldog is a dog. A chihuahua is a dog. This is super important when talking about inheritance because you are building a representation of a mental (or domain) model. It makes sense that bulldog is a dog. It would NOT make sense for a class named PeatMoss to inherit from the Dog abstract class, even if you needed Peat Moss to have some method named "Bark". Peat Moss is not a Dog.
Interfaces are a very different construct. Interfaces guarantee that an object, whatever that object is, can perform some sort of action. A class that implements IComparable can be compared (CompareTo method). It is not an object of type "comparable". If we implement IEnumerable our objects must create an enumerator to walk a collection. We have not created an object of type "Enumerable". We have just guaranteed a behavior without layering on any other notions about what our object is. (Dogs could implement IComparable as could PeatMoss without any dissonance in our domain/mental model).
Abstract classes are about inheritance hierarchies and the domain model you are working in. Interfaces deal with specific, constrained behaviors you need a class to have.