C# OOP – Should We Inherit from Base Class and Implement Interface?

cinheritanceinterfacesobject-oriented

I am new to object oriented design and learning about interfaces and design patterns. In this example, I am trying to create class for cars. My question:

Is it good practice to use base class and then inherit from it. And then use interfaces for implementing different functions? If not, then what would be the best way to implement this.

Base Class:

    class BaseCar
        {
            public string color { get; set; }
            public double price { get; set; }

            public string carType { get; set; }
        }

Interface: 
interface ICarFunctions
    {
        void brakeSystem();

        void drivingModes(string mode);

        void entertainmentSystem();

    }

Now I am trying to create concrete classes

 class BmwCar : BaseCar, ICarFunctions
    {

        public void brakeSystem()
        {
            Console.WriteLine("Brake in less than 0.02ms");
        }

        public void drivingModes(string mode)
        {
            switch(mode) 

            {
                case "mountain":
                    {
                        Console.WriteLine("Switching to 4x4 mode");
                        break;
                    }

                default:
                    {
                        Console.WriteLine("Normal Mode");
                        break;
                    }

            }

        }

        public void entertainmentSystem()
        {
            Console.WriteLine("Music, Navigation");
        }
    }

Now my question is: Is it good practice to use a base class and then inherit from it? And then use interfaces for implementing different functions?

My second question is if interface should have only one function (Single responsibility principle) or can it can have multiple functions which need to be implemented?

Best Answer

Your first question

Is it good practice to use base class and then inherit from it. And then use interfaces for implementing different functions?

There is no inherent requirement which states that methods should be implemented via an interface and fields/properties should be inherited/defined in the class. This is not a good way to separate the logic, as you're essentially preventing any meaningful relation to exist between a class' fields/properties and its methods.

One obvious limitation is that interfaces only deal with public members. If you applied your approach to the letter, it would be impossible to use private class methods.

Similarly, you'd be unable to define a public property via an interface, which is going to hamper the usability of your interfaces. As a simple example, IList exposes public properties like Count and IsReadOnly. Could you technically handle that by using methods (GetCount() and IsReadOnly())? Sure, but what is the point of forcing yourself to only using methods for public access? Public properties exist for a reason: to severely cut down on the boilerplate getFoo()/setFoo() methods that you'd end up having to write for every publically accessible field you want.

Another limitation is that your code never defines that a BaseCar has a brakeSystem() method. For example, there is no problem with making a BaseCar that does not implement the necessary interface.

public class FlaterCar : BaseCar { }

The compiler has no issue with this. You never stated that you expect both the base class and interface to be used in conjuction with each other. This means that you're unable to create a method which is able to handle any BaseCar and make it brake. This is impossible:

public void MakeThisCarBrake(BaseCar car)
{
    car.brakeSystem(); //compiler error, brakeSystem is not a known method of BaseCar
}

This means that your base class has become impossible to use for a lot of common polymorphism use cases, and you would end up constantly having to do if(car is ICarFuntions) car.brakeSystem();, which violates LSP and OCP.

What you would expect is to be able to handle your base type without needing to guess about any interfaced the actual derived type might implement.

public void LetThisAnimalMakeASound(Animal animal)
{
    animal.MakeSound();
}

But this requires both the base and derived class to share the same method signature (regardless of whether the derived classes override the base class' method body or not).

public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine(" ...silence... ");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Woof woof!");
    }
}

public class Duck : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Quack!");
    }
}

When you do put your methods in an interface, the only way to ensure that this still works is to have the base class implement the interface.

public interface IMakeSound
{
    void MakeSound();
}

public class Animal : IMakeSound
{
    public virtual void MakeSound()
    {
        Console.WriteLine(" ...silence... ");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Woof woof!");
    }
}

The derived class doesn't directly implement the interface itself, it merely inherits the interface implementation from its base class (and then chooses to override it, but that's not a requirement, it could choose to keep the base method as is).

But when you get to that point, you might not even need the interface anymore since you're already stuck having to define the implementation in the base class anyway, which means the interface might be a pointless second layer; unless this interface is used in many different classes and has its own (different) fuctional purpose compared to the base class.


Your second question

My second question is that should interface have only one function(Single responsibility principle) or it can have multiple functions to be implemented.

There is no rule about the amount of methods. It's all about the functional independence. For more information, read up on the interface segregation principle (ISP), the I in SOLID. (Note: I just picked one link, many other references exist).

In essense, it boils down to whether your interface can be split or not. Let's take your case:

public interface ICarFunctions
{
    void brakeSystem();
    void drivingModes(string mode);
    void entertainmentSystem();
}

The first question you should ask yourself: is this a package deal? Does every car with a brake system have an entertainment system? Does every car with a driving mode have brakes?

The contextual answer here is no. There is no inherent requirement that when you have brakes, you must have an entertainment system, and thus this interface can be split into separate interfaces.

However, that's not the same as saying that an interface can only have one method. There are cases where you cannot split an interface, e.g.:

public interface IEntertainmentSystem
{
    void IncreaseVolume();
    void DecreaseVolume();
    void Play();
    void Pause();
    void Previous();
    void Next();
}

These standard media player functions can be considered a package deal. It makes no sense to only have some of these features. Therefore, this interface should not be split up any further since it would not make sense to use only a subset of these functionalities and not the rest.

Related Topic