Overview
Understanding the differences between abstract classes and interfaces in C# is crucial for designing flexible and maintainable object-oriented systems. Abstract classes allow you to define some behaviors while leaving others to be implemented by derived classes, whereas interfaces define a contract that implementing classes must follow, without providing any implementation details. Choosing between the two depends on the design requirements of your application.
Key Concepts
- Inheritance vs. Polymorphism: Abstract classes are used for sharing a common implementation among related classes, while interfaces are used for defining a common interface for unrelated classes.
- Access Modifiers: Abstract classes can have access modifiers for their members, allowing for public, protected, or private implementations, whereas interface members are implicitly public.
- Implementation and State: Abstract classes can hold state (fields) and provide concrete method implementations, but interfaces cannot hold state and only declare method signatures.
Common Interview Questions
Basic Level
- What is an abstract class and an interface in C#?
- Can you give a simple example of an abstract class and an interface?
Intermediate Level
- When should you use an abstract class instead of an interface?
Advanced Level
- How would you design a system that requires both the use of abstract classes and interfaces?
Detailed Answers
1. What is an abstract class and an interface in C#?
Answer: In C#, an abstract class is a class that cannot be instantiated and may contain abstract methods, which are methods without an implementation. They are intended to be inherited by derived classes, which then implement the abstract methods. An interface, on the other hand, is a contract that any class or struct that implements it must follow. An interface only contains declarations of methods, properties, events, or indexers, and no implementations.
Key Points:
- Abstract classes can contain implementations for some of its members.
- Interfaces cannot contain any implementation logic.
- A class can implement multiple interfaces but can only inherit from one abstract class.
Example:
public abstract class Animal
{
public void Breathe() // Non-abstract method
{
Console.WriteLine("Breathing...");
}
public abstract void MakeSound(); // Abstract method
}
public interface IMovable
{
void Move(); // Method signature
}
// Implementing an abstract class and an interface
public class Dog : Animal, IMovable
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
public void Move()
{
Console.WriteLine("Running");
}
}
2. Can you give a simple example of an abstract class and an interface?
Answer: Sure, the above example also serves as a simple illustration of both concepts. Here, Animal
is an abstract class that provides a concrete implementation of the Breathe
method and an abstract declaration of the MakeSound
method. IMovable
is an interface with a declaration of the Move
method. The Dog
class then inherits from Animal
and implements IMovable
, providing implementations for both MakeSound
and Move
.
3. When should you use an abstract class instead of an interface?
Answer: You should use an abstract class when you want to provide common base functionality to derived classes, not just a contract, and when you expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (like protected or private). If you're designing small, concise bits of functionality that can be added to any class, then an interface would be the better choice.
Key Points:
- Use abstract classes when sharing code among closely related classes is needed.
- Use interfaces when you need to define a role that can be played by classes from different hierarchies.
- Interfaces are ideal for defining capabilities that can be added to any class.
4. How would you design a system that requires both the use of abstract classes and interfaces?
Answer: Designing a system that leverages both abstract classes and interfaces involves identifying what common behaviors or states can be abstracted into a base class and what capabilities or roles can be defined as interfaces. For instance, in a graphics system, you might have an abstract Shape
class that provides basic fields and methods common to all shapes (like Area
or Position
), and interfaces like IDrawable
and ITransformable
that define the capability to be drawn on screen or transformed, respectively.
public abstract class Shape
{
public double PositionX { get; set; }
public double PositionY { get; set; }
public abstract double Area();
}
public interface IDrawable
{
void Draw();
}
public interface ITransformable
{
void Rotate(double angle);
void Scale(double factor);
}
public class Circle : Shape, IDrawable, ITransformable
{
public double Radius { get; set; }
public override double Area()
{
return Math.PI * Radius * Radius;
}
public void Draw()
{
Console.WriteLine("Drawing Circle");
}
public void Rotate(double angle)
{
// Implementation for rotating the shape
}
public void Scale(double factor)
{
Radius *= factor;
}
}
This design allows the Circle
class to inherit state and behavior from Shape
while also committing to additional capabilities defined by IDrawable
and ITransformable
.