Interview Series: Abstract Class vs Interface in C#
Interviewer Question 1: What is the basic difference between an abstract class and an interface in C#?
Answer: The main difference is that an abstract class can have both abstract methods (without implementation) and concrete methods (with implementation), while an interface only defines abstract methods (until C# 8.0, where default implementations were introduced).
- Abstract Class: Can have both method definitions and implementations.
- Interface: Defines only method signatures, and any class implementing the interface must provide implementations for all its members.
Interviewer Question 2: Can you explain the usage scenarios for abstract class vs interface?
Answer: An abstract class is used when you want to provide some common functionality along with abstract methods that subclasses must implement. It’s ideal when you have a common base class for related objects.
An interface is used when you want to enforce a contract for multiple unrelated classes. It’s ideal for scenarios where multiple implementations are expected but they do not need to share common behavior.
Example:
- Use an abstract class for vehicles (e.g.,
Car
,Bike
) to provide a method likeDisplayInfo()
, but leaveCalculateFuelEfficiency()
to be implemented by each vehicle. - Use an interface when you want all payment methods (
CreditCardPayment
,PayPalPayment
) to implement theProcessPayment()
method without shared behavior.
Interviewer Question 3: Can an abstract class have a constructor?
Answer: Yes, an abstract class can have a constructor. Although you cannot instantiate an abstract class directly, the constructor is called when a subclass is instantiated. It is used to initialize common properties for all subclasses.
Example:
public abstract class Vehicle
{
public string Name { get; set; }
public Vehicle(string name)
{
Name = name;
}
}
public class Car : Vehicle
{
public Car(string name) : base(name) {}
}
When you instantiate Car
, the constructor of Vehicle
will be invoked to initialize the Name
property.
Interviewer Question 4: Can a class implement multiple interfaces? What about inheriting multiple abstract classes?
Answer: Yes, a class can implement multiple interfaces. This is one of the key benefits of using interfaces as it allows for multiple inheritance of behavior.
However, a class cannot inherit from multiple abstract classes, as C# does not support multiple inheritance for classes. A class can inherit from only one abstract class but can implement multiple interfaces.
Example:
public class Car : Vehicle, IPaymentProcessor, IComparable
{
// Implement abstract methods from Vehicle and interface methods
}
Interviewer Question 5: How would you decide when to use an abstract class over an interface?
Answer:
- Use an abstract class when:
- You need to share common behavior or logic between subclasses.
- You expect some methods to be the same across all subclasses (i.e., shared logic).
- The classes share an “is-a” relationship (e.g., a
Car
is aVehicle
).
- Use an interface when:
- You want to enforce a contract for unrelated classes that don’t need common behavior.
- You need multiple inheritance (since a class can implement multiple interfaces).
- The classes share a “can-do” relationship (e.g., a class that can-do
IDisposable
,IPaymentProcessor
).
Interviewer Question 6: Can you give a real-time example for when you’d use an interface in C#?
Answer: Consider a payment processing system. You may have different types of payments like CreditCardPayment
, PayPalPayment
, or BankTransferPayment
, and they all need to implement a method ProcessPayment()
.
public interface IPaymentProcessor
{
void ProcessPayment(double amount);
}
public class CreditCardPayment : IPaymentProcessor
{
public void ProcessPayment(double amount)
{
Console.WriteLine($"Processing Credit Card Payment of ${amount}");
}
}
public class PayPalPayment : IPaymentProcessor
{
public void ProcessPayment(double amount)
{
Console.WriteLine($"Processing PayPal Payment of ${amount}");
}
}
This ensures that all payment methods implement the ProcessPayment()
method, making it easier to extend the system when a new method, like BitcoinPayment
, is added.
Interviewer Question 7: What are some best practices when using abstract classes and interfaces?
Answer:
- Use abstract classes if you need to provide a common base and shared functionality for derived classes.
- Use interfaces for loose coupling and flexibility, especially in scenarios where you expect many implementations of the same functionality.
- Favor interfaces over abstract classes if you foresee the need for multiple inheritance.
- Keep your interfaces small and focused on one responsibility. Avoid creating “fat” interfaces that require too many methods to be implemented by classes.
Interviewer Question 8: What are the limitations of abstract classes and interfaces? When should you NOT use each?
Limitations of Abstract Classes
- No multiple inheritance: A class can only inherit one abstract class, limiting flexibility.
- Tighter coupling: Abstract classes can tightly couple base and derived classes, making it harder to introduce changes.
When NOT to use Abstract Classes
- If you need multiple inheritance.
- If the classes are unrelated.
Limitations of Interfaces
- Cannot share common code: Interfaces only define signatures, not implementations.
- Versioning issues: Adding methods to an interface requires all implementing classes to update their code.
When NOT to use Interfaces
- If you want to provide shared behavior.
- If maintaining backward compatibility is crucial.
Real-World Example of Using Abstract Classes and Interfaces
Scenario: Payment Processing System
Using abstract classes and interfaces, you can create a flexible and scalable payment system.
Abstract Class Example:
public abstract class PaymentProcessor
{
public void LogTransaction(double amount)
{
Console.WriteLine($"Logging transaction of ${amount}");
}
public abstract void ProcessPayment(double amount);
}
public class CreditCardPayment : PaymentProcessor
{
public override void ProcessPayment(double amount)
{
LogTransaction(amount);
Console.WriteLine($"Processing Credit Card Payment of ${amount}");
}
}
Interface Example:
public interface IPaymentProcessor
{
void ProcessPayment(double amount);
}
public class PayPalPayment : IPaymentProcessor
{
public void ProcessPayment(double amount)
{
Console.WriteLine($"Processing PayPal Payment of ${amount}");
}
}