Clear Differences: 6 Key Differences Between Abstract Classes and Interfaces in C#

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.

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:

  1. Classes can have constructors and fields.
  2. Classes can have method implementations.
  3. Classes can have access modifiers for their members.
  4. 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 and Balance) and methods (Deposit and Withdraw) for all bank accounts.
  • SavingsAccount and CheckingAccount are concrete subclasses of BankAccount. They inherit common properties and methods from BankAccount and provide specific implementations for the Withdraw method based on their rules (e.g., overdraft limit for checking accounts, interest rate for savings accounts).
  • Since Withdraw is an abstract method in BankAccount, 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:

  1. Interfaces cannot have constructors or fields.
  2. Interfaces only have method and property signatures.
  3. Interfaces cannot have modifiers for their members (they are implicitly public).
  4. 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 methods TurnOn, TurnOff, and a read-only property IsOn.
  • Battery and ElectricOutlet are concrete classes that implement the IPowerSource 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 implements IPowerSource 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

  1. 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.
    • 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.
  2. 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.
  3. 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.
  4. 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.
  5. Access Modifiers:
    • Abstract Class:
      • Can have access modifiers like public, protected, internal, or protected internal for its members.
      • This allows control over visibility and accessibility within the same assembly or derived classes.
    • Interface:
      • All members of an interface are public by default and cannot have access modifiers.
      • They are accessible to any class implementing the interface.
  6. 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.

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#.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top