This may be a generic OOP question. I wanted to do a generic comparison between an interface and an abstract class on the basis of their usage.
When wou
I think the most succinct way of putting it is the following:
Shared properties => abstract class.
Shared functionality => interface.
And to put it less succinctly...
Abstract Class Example:
public abstract class BaseAnimal
{
public int NumberOfLegs { get; set; }
protected BaseAnimal(int numberOfLegs)
{
NumberOfLegs = numberOfLegs;
}
}
public class Dog : BaseAnimal
{
public Dog() : base(4) { }
}
public class Human : BaseAnimal
{
public Human() : base(2) { }
}
Since animals have a shared property - number of legs in this case - it makes sense to make an abstract class containing this shared property. This also allows us to write common code that operates on that property. For example:
public static int CountAllLegs(List animals)
{
int legCount = 0;
foreach (BaseAnimal animal in animals)
{
legCount += animal.NumberOfLegs;
}
return legCount;
}
Interface Example:
public interface IMakeSound
{
void MakeSound();
}
public class Car : IMakeSound
{
public void MakeSound() => Console.WriteLine("Vroom!");
}
public class Vuvuzela : IMakeSound
{
public void MakeSound() => Console.WriteLine("VZZZZZZZZZZZZZ!");
}
Note here that Vuvuzelas and Cars are completely different things, but they have shared functionality: making a sound. Thus, an interface makes sense here. Further, it will allow programmers to group things that make sounds together under a common interface -- IMakeSound in this case. With this design, you could write the following code:
List soundMakers = new List();
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Vuvuzela());
foreach (IMakeSound soundMaker in soundMakers)
{
soundMaker.MakeSound();
}
Can you tell what that would output?
Lastly, you can combine the two.
Combined Example:
public interface IMakeSound
{
void MakeSound();
}
public abstract class BaseAnimal : IMakeSound
{
public int NumberOfLegs { get; set; }
protected BaseAnimal(int numberOfLegs)
{
NumberOfLegs = numberOfLegs;
}
public abstract void MakeSound();
}
public class Cat : BaseAnimal
{
public Cat() : base(4) { }
public override void MakeSound() => Console.WriteLine("Meow!");
}
public class Human : BaseAnimal
{
public Human() : base(2) { }
public override void MakeSound() => Console.WriteLine("Hello, world!");
}
Here, we're requiring all BaseAnimals make a sound, but we don't know its implementation yet. In such a case, we can abstract the interface implementation and delegate its implementation to its subclasses.
One last point, remember how in the abstract class example we were able to operate on the shared properties of different objects and in the interface example we were able to invoke the shared functionality of different objects? In this last example, we could do both.