Search code examples
oopinterfacelanguage-agnosticbase-classstatic-typing

Interface vs Base class


When should I use an interface and when should I use a base class?

Should it always be an interface if I don't want to actually define a base implementation of the methods?

If I have a Dog and Cat class. Why would I want to implement IPet instead of PetBase? I can understand having interfaces for ISheds or IBarks (IMakesNoise?), because those can be placed on a pet by pet basis, but I don't understand which to use for a generic Pet.


Solution

  • Let's take your example of a Dog and a Cat class, and let's illustrate using C#:

    Both a dog and a cat are animals, specifically, quadruped mammals (animals are waaay too general). Let us assume that you have an abstract class Mammal, for both of them:

    public abstract class Mammal
    

    This base class will probably have default methods such as:

    • Feed
    • Mate

    All of which are behavior that have more or less the same implementation between either species. To define this you will have:

    public class Dog : Mammal
    public class Cat : Mammal
    

    Now let's suppose there are other mammals, which we will usually see in a zoo:

    public class Giraffe : Mammal
    public class Rhinoceros : Mammal
    public class Hippopotamus : Mammal
    

    This will still be valid because at the core of the functionality Feed() and Mate() will still be the same.

    However, giraffes, rhinoceros, and hippos are not exactly animals that you can make pets out of. That's where an interface will be useful:

    public interface IPettable
    {
        IList<Trick> Tricks{get; set;}
        void Bathe();
        void Train(Trick t);
    }
    

    The implementation for the above contract will not be the same between a cat and dog; putting their implementations in an abstract class to inherit will be a bad idea.

    Your Dog and Cat definitions should now look like:

    public class Dog : Mammal, IPettable
    public class Cat : Mammal, IPettable
    

    Theoretically you can override them from a higher base class, but essentially an interface allows you to add on only the things you need into a class without the need for inheritance.

    Consequently, because you can usually only inherit from one abstract class (in most statically typed OO languages that is... exceptions include C++) but be able to implement multiple interfaces, it allows you to construct objects in a strictly as required basis.