In C# programming, abstract classes and interfaces play an important role in defining class structure and ensuring code reusability. In this article, we will explore the differences between abstract classes and interfaces in C#, focusing on advanced developer understanding with proper steps and examples.
Table of Contents
What is abstract class?
An abstract class in C# is a class that cannot be instantiated directly. Instead, it serves as a blueprint or template for other classes to inherit from. Abstract classes are defined using the abstract
keyword. They can contain both abstract and non-abstract members, including methods, properties, events, indexers, fields, and constructors.
Key Points about Abstract Classes:
- Classes can have constructors and fields.
- Classes can have method implementations.
- Classes can have access modifiers for their members.
- A class can inherit from only one abstract class.
Abstract Class Example
// Abstract class representing a bank account
public abstract class BankAccount
{
// Common properties for all accounts
public string AccountNumber { get; set; }
public decimal Balance { get; protected set; }
// Constructor
public BankAccount(string accountNumber)
{
AccountNumber = accountNumber;
Balance = 0;
}
// Common methods for all accounts
public void Deposit(decimal amount)
{
Balance += amount;
Console.WriteLine($"Deposited {amount:C}. New balance: {Balance:C}");
}
public abstract void Withdraw(decimal amount); // Abstract method to be implemented by subclasses
}
// Concrete subclass representing a Savings Account
public class SavingsAccount : BankAccount
{
public decimal InterestRate { get; private set; }
public SavingsAccount(string accountNumber, decimal interestRate) : base(accountNumber)
{
InterestRate = interestRate;
}
public override void Withdraw(decimal amount)
{
if (Balance - amount >= 0)
{
Balance -= amount;
Console.WriteLine($"Withdrawn {amount:C}. New balance: {Balance:C}");
}
else
{
Console.WriteLine("Insufficient funds.");
}
}
}
// Concrete subclass representing a Checking Account
public class CheckingAccount : BankAccount
{
public decimal OverdraftLimit { get; private set; }
public CheckingAccount(string accountNumber, decimal overdraftLimit) : base(accountNumber)
{
OverdraftLimit = overdraftLimit;
}
public override void Withdraw(decimal amount)
{
if (Balance - amount >= -OverdraftLimit)
{
Balance -= amount;
Console.WriteLine($"Withdrawn {amount:C}. New balance: {Balance:C}");
}
else
{
Console.WriteLine("Exceeded overdraft limit.");
}
}
}
In this example:
BankAccount
is an abstract class that defines common properties (AccountNumber
andBalance
) and methods (Deposit
andWithdraw
) for all bank accounts.SavingsAccount
andCheckingAccount
are concrete subclasses ofBankAccount
. They inherit common properties and methods fromBankAccount
and provide specific implementations for theWithdraw
method based on their rules (e.g., overdraft limit for checking accounts, interest rate for savings accounts).- Since
Withdraw
is an abstract method inBankAccount
, each subclass must provide its own implementation, ensuring that withdrawal logic is tailored to each account type.
Interface in C#
A C# interface defines a convention that a class must follow by implementing all members defined in the interface. It contains only the signatures of methods, properties, events, and indexers. Since C# 8, Default implementations can also be included in interfaces.
Key Points about Interfaces:
- Interfaces cannot have constructors or fields.
- Interfaces only have method and property signatures.
- Interfaces cannot have modifiers for their members (they are implicitly public).
- A class can implement multiple interfaces.
Interface Example C#
// Interface representing a power source
public interface IPowerSource
{
void TurnOn();
void TurnOff();
bool IsOn { get; }
}
// Concrete class representing a Battery
public class Battery : IPowerSource
{
public bool IsOn { get; private set; }
public void TurnOn()
{
IsOn = true;
Console.WriteLine("Battery turned on.");
}
public void TurnOff()
{
IsOn = false;
Console.WriteLine("Battery turned off.");
}
}
// Concrete class representing an Electric Outlet
public class ElectricOutlet : IPowerSource
{
public bool IsOn { get; private set; }
public void TurnOn()
{
IsOn = true;
Console.WriteLine("Electric outlet turned on.");
}
public void TurnOff()
{
IsOn = false;
Console.WriteLine("Electric outlet turned off.");
}
}
// Device that can be powered by a power source
public class ElectronicDevice
{
private readonly IPowerSource _powerSource;
public ElectronicDevice(IPowerSource powerSource)
{
_powerSource = powerSource;
}
public void UseDevice()
{
if (_powerSource.IsOn)
{
Console.WriteLine("Device is operational.");
}
else
{
Console.WriteLine("Device cannot be used, power source is off.");
}
}
}
In this example:
IPowerSource
is an interface representing a power source. It defines methodsTurnOn
,TurnOff
, and a read-only propertyIsOn
.Battery
andElectricOutlet
are concrete classes that implement theIPowerSource
interface. They provide their own implementations for turning on/off the power source.ElectronicDevice
is a class that depends on a power source (IPowerSource
). It can use any device that implementsIPowerSource
without knowing the specific type of power source (battery or electric outlet).
Battery battery = new Battery();
ElectricOutlet outlet = new ElectricOutlet();
ElectronicDevice device1 = new ElectronicDevice(battery);
ElectronicDevice device2 = new ElectronicDevice(outlet);
device1.UseDevice(); // Output: "Device cannot be used, power source is off."
battery.TurnOn();
device1.UseDevice(); // Output: "Device is operational."
device2.UseDevice(); // Output: "Device cannot be used, power source is off."
outlet.TurnOn();
device2.UseDevice(); // Output: "Device is operational."
In this scenario, the IPowerSource
interface allows for flexibility in using different types of power sources (Battery
, ElectricOutlet
) with electronic devices (ElectronicDevice
). The interface defines a contract that any power source must adhere to, ensuring consistent behavior across different implementations.
Differences Between Abstract Classes and Interfaces
- Definition:
- Abstract Class:
- An abstract class is declared using the
abstract
keyword. - It can have both abstract and non-abstract members (methods, properties, events).
- Abstract classes may also contain fields and constructors.
- An abstract class is declared using the
- Interface:
- An interface is declared using the
interface
keyword. - It contains only method signatures, properties, events, and indexers without any implementation.
- Interfaces do not include fields, constructors, or concrete methods.
- Interface (Since C# 8): Can include default implementations for methods, properties, indexers, and events. These default implementations provide a base implementation that classes implementing the interface can use directly or override if needed.
- An interface is declared using the
- Abstract Class:
- Inheritance:
- Abstract Class:
- Supports single class inheritance, meaning a class can inherit from only one abstract class.
- Abstract classes can also inherit from other abstract or non-abstract classes.
- Interface:
- Supports multiple interface inheritance, allowing a class to implement multiple interfaces.
- This enables a class to define its behavior according to different contracts specified by various interfaces.
- Abstract Class:
- Default Implementation:
- Abstract Class:
- Can provide default implementations for some or all of its members.
- Subclasses can choose to override these implementations or use them as-is.
- Interface:
- Does not contain any implementation code.
- It only defines method signatures, properties, events, and indexers without specifying how they should be implemented.
- Abstract Class:
- Constructor:
- Abstract Class:
- Can have constructors that are used for initializing the state of the abstract class and its subclasses.
- Subclasses must call the constructor of the abstract class explicitly.
- Interface:
- Cannot have constructors because they do not contain any implementation.
- Classes implementing an interface must use their own constructors for initialization.
- Abstract Class:
- Access Modifiers:
- Abstract Class:
- Can have access modifiers like
public
,protected
,internal
, orprotected internal
for its members. - This allows control over visibility and accessibility within the same assembly or derived classes.
- Can have access modifiers like
- Interface:
- All members of an interface are
public
by default and cannot have access modifiers. - They are accessible to any class implementing the interface.
- All members of an interface are
- Abstract Class:
- Use Cases:
- Abstract Class:
- Typically used to define common behavior and structure for a group of related classes.
- Abstract classes provide a way to encapsulate common functionality and state among subclasses.
- Interface:
- Used to define contracts or capabilities that unrelated classes can implement.
- Interfaces allow classes from different inheritance hierarchies to share common functionality without requiring a common base class.
- Abstract Class:
Example (Abstract Class and Interface)
// Abstract Class
public abstract class Shape
{
public abstract void Draw(); // Abstract method
public void Display() // Concrete method
{
Console.WriteLine("Displaying shape");
}
}
// Interface
public interface IResizable
{
void Resize(int width, int height);
}
// Concrete Class implementing Abstract Class and Interface
public class Rectangle : Shape, IResizable
{
public override void Draw()
{
Console.WriteLine("Drawing rectangle");
}
public void Resize(int width, int height)
{
Console.WriteLine($"Resizing rectangle to {width}x{height}");
}
}
In this example, Shape
is an abstract class with an abstract Draw
method and a concrete method Display
. IResizable
is an interface that defines Resize
method signatures. The Rectangle
class inherits from Shape
and implements IResizable
, providing implementations for the abstract and interface methods.
Here, you can checkout our post on Exception handling in C# Programming with Example
Conclusion
Abstract classes and interfaces serve different purposes in C# programming. Abstract classes are used for defining common behavior and providing default implementations, while interfaces are used for defining contracts that classes must adhere to. Understanding the differences between them is essential for designing flexible and maintainable code in C#.
I hope this article clarifies the difference between abstract classes and interfaces in C#.