Understanding C# Abstract Class With Examples

An abstract class in C# serves as a blueprint for other classes. It cannot be instantiated on its own and is meant to be a base class of other classes. It may contain both abstract and non-abstract members (methods, properties, or events). The abstract members must be implemented by non-abstract derived classes.

csharp-abstract-class

Declaring Abstract Classes in C#

We can define an abstract class in C# using the abstract keyword. An abstract class can have regular methods with concrete implementation along with abstract members (without implementation). 

Here is the syntax:

public abstract class MyAbstractClass
{
    // Abstract method (no implementation)
    public abstract void AbstractMethod();

    // Regular method with implementation
    public void RegularMethod()
    {
        // Code implementation here
    }
}

C# Abstract Class vs. Concrete Class

Here is a comparison between Abstract Class and Concrete Class in C#:

AspectAbstract ClassConcrete Class
Instantiation:An abstract class cannot be directly instantiated using the new keyword.Unlike abstract classes, concrete classes can be directly instantiated using the new keyword. They are complete and provide full functionality since all their members have concrete implementations.
Purpose:The abstract class serves as a blueprint for other derived classes.A concrete class represents a complete, tangible entity.
Abstract Members:An abstract class can have abstract members with no implementation.A concrete class cannot have abstract members.
Complete/Partial Members:An abstract class can have both abstract members (without implementation) and concrete members (non-abstract members with implementation).A concrete class may have all concrete members (non-abstract) with implementations.
Inheritance:It Supports inheritance.Supports inheritance.
Instantiable Subclasses:An abstract class must depend on subclassed to create instances.A Concrete class or normal class can be directly instantiated.
Usage:An abstract class can be used when you want to provide a common structure and contract for derived classes.It can be used when you have a specific, standalone entity with defined behavior.
Example:public abstract class Shape
{
public abstract void Draw();
}
public class Circle
{
public void Draw()
{ /* Code to draw a circle */
}
}

In short, A concrete class in C# is a regular class that can be instantiated, while an abstract class cannot be instantiated directly. The purpose of an abstract class is to provide a common functionality, structure and contract for its subclasses.

C# Abstract Method

In C#, an abstract method is a method declared in an abstract class that does not have an implementation. Instead, its implementation is left to be implemented by the derived classes. 

Abstract methods are declared with the abstract keyword and end with a semicolon without providing any curly braces containing the method body.

Let’s look at a simple code example to understand abstract methods:

using System;

// Step 1: Define an abstract class with an abstract method
public abstract class Shape
{
    // Abstract method for calculating area (no implementation)
    public abstract double CalculateArea();
}

// Step 2: Create a concrete class that inherits from the abstract class
public class Circle : Shape
{
    // Properties specific to the Circle
    public double Radius { get; set; }

    // Constructor
    public Circle(double radius)
    {
        Radius = radius;
    }

    // Implement the abstract method for Circle
    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}

// Step 3: Main program
public class Program
{
    public static void Main()
    {
        // Create an instance of Circle
        Circle circle = new Circle(radius: 5);

        // Call the abstract method, which will execute the concrete implementation in the Circle class
        double area = circle.CalculateArea();

        Console.WriteLine($"Area of the circle: {area}");
    }
}

Output:

Area of the circle: 78.5398163397448

When to Use Abstract Classes?

An abstract class allows us to create a common base class for related classes. It allows code reusability and enforcing a contract among derived classes. 

Here are some scenarios where using abstract classes is beneficial:

  1. Code Reusability: Abstract classes promote code reusability by encapsulating common functionality in a single class. Subclasses can extend this functionality and override the existing implementation if needed.
  2. Defining a Common Base: When you have a group of related classes with common characteristics or functionality, you can use an abstract class to define a base class. The abstract class can contain shared methods, properties, and fields, which can reduce code duplication among subclasses.
  3. Providing Default Implementation: Abstract classes can have both abstract (without implementation) and concrete (with implementation) members. This enables you to provide a default implementation for certain methods while enforcing derived classes to implement other methods.
  4. Enforcing Rules and Contracts: Abstract classes can define a contract for derived classes, specifying what methods they must implement or what properties they must provide. This ensures that all subclasses follow the same set of rules and behave consistently.

Example: Animals and Their Sounds

Let’s consider a real-world example of animals and their sounds. We want to define a set of animals, each making a specific sound.

We will use an abstract class to represent the base animal and derive concrete animal classes representing individual animal species.

using System;

// Step 1: Define the abstract class Animal
public abstract class Animal
{
    // Properties that all animals have
    public string Name { get; set; }
    public string Sound { get; protected set; }

    // Abstract method for making the sound
    public abstract void MakeSound();

    // Concrete method to display the animal's information
    public void DisplayInfo()
    {
        Console.WriteLine($"The {Name} says '{Sound}'.");
    }
}

// Step 2: Define concrete animal classes inheriting from Animal
public class Dog : Animal
{
    public Dog()
    {
        Name = "Dog";
        Sound = "Woof";
    }

    public override void MakeSound()
    {
        Console.WriteLine("Woof Woof!");
    }
}

public class Cat : Animal
{
    public Cat()
    {
        Name = "Cat";
        Sound = "Meow";
    }

    public override void MakeSound()
    {
        Console.WriteLine("Meow Meow!");
    }
}

// Step 3: Main program
public class Program
{
    public static void Main()
    {
        // Create instances of animal classes
        Animal dog = new Dog();
        Animal cat = new Cat();

        // Display information and make sounds
        dog.DisplayInfo();
        dog.MakeSound();

        cat.DisplayInfo();
        cat.MakeSound();
    }
}

Output:

The Dog says 'Woof'.
Woof Woof!
The Cat says 'Meow'.
Meow Meow!

Features of C# Abstract Class:

C# abstract classes offer several important features that enhance the design and functionality of object-oriented programming. 

Here are the key features of C# abstract class:

  1. Cannot be Instantiated: Abstract classes cannot be directly instantiated using the new keyword. This is because abstract classes may contain abstract members without implementations, making them incomplete for use.
  2. Can Contain Abstract Members: Abstract classes can have abstract members, such as abstract methods, properties, and events. These abstract members act as placeholders and must be implemented in derived classes.
  3. Can Contain Concrete Members: Abstract classes can also include regular, concrete (non-abstract) members with complete implementations. These concrete members can be used directly by derived classes without any modifications.
  4. Supports Inheritance: Abstract classes support inheritance, allowing derived classes (subclasses) to extend and specialize the abstract class. When a class inherits from an abstract class, it must provide concrete implementations for all abstract members, or the subclass itself becomes abstract.
  5. Provides a Common Base: Abstract classes are designed to provide a common base with some default behavior to all classes that inherit from them. They define a contract that derived classes must follow to ensure a consistent structure and functionality across related classes.
  6. Allows Abstraction and Encapsulation: Abstract classes promote abstraction by hiding the implementation details of the abstract members. They also support encapsulation by providing access modifiers for members, controlling their visibility and accessibility in derived classes.
  7. Enables Polymorphism: C# promotes polymorphism by using abstract classes and their abstract members. Derived classes can provide specific implementations for abstract members, allowing different objects to behave differently while following a common interface.
  8. Facilitates Code Reusability: Abstract classes promote code reusability by encapsulating common functionality in a single class. Subclasses or derived classes can extend this functionality.
  9. Support Interface Implementation: Abstract classes can implement one or more interfaces, providing a powerful way to define shared functionality through the abstract class and enforce specific behavior through interfaces.
  10. Used for Complex Hierarchies: Abstract classes are particularly useful when designing complex class hierarchies, where multiple classes must share some common behavior but have specific implementations for certain situations.

Using Abstract Class for Abstraction:

Abstraction is all about keeping things simple on the outside and hiding the complicated stuff inside. It’s like using a TV remote without knowing how it works inside.

Abstraction in C# is the process of hiding the internal details and showing only the functionality of a class or a method. It can be achieved using abstract classes and abstract methods. An abstract class is a class that cannot be instantiated by its own but can be inherited by other derived classes. An abstract method is a method that has no body but must be overridden by the derived classes.

In this real-world example, let’s model a basic banking system using an abstract class to achieve abstraction.

We’ll create an abstract class BankAccount that defines common functionalities for different types of bank accounts and then derive two specific account classes, SavingsAccount and CurrentAccount, from the abstract class.

Let’s demonstrate how to use an abstract class to achieve abstraction with an example:

using System;

// Step 1: Define an abstract class for BankAccount
public abstract class BankAccount
{
    // Common properties for all bank accounts
    public string AccountNumber { get; }
    public string AccountHolder { get; }
    public decimal Balance { get; protected set; }

    // Constructor for BankAccount
    public BankAccount(string accountNumber, string accountHolder, decimal initialBalance)
    {
        AccountNumber = accountNumber;
        AccountHolder = accountHolder;
        Balance = initialBalance;
    }

    // Abstract method for withdrawing money
    public abstract void Withdraw(decimal amount);

    // Concrete method for depositing money
    public void Deposit(decimal amount)
    {
        Balance += amount;
        Console.WriteLine($"Deposited: ${amount}, Current Balance: ${Balance}");
    }

    // Concrete method to display account information
    public void DisplayAccountInfo()
    {
        Console.WriteLine($"Account Number: {AccountNumber}");
        Console.WriteLine($"Account Holder: {AccountHolder}");
        Console.WriteLine($"Balance: ${Balance}");
    }
}

// Step 2: Create specific account classes inheriting from BankAccount
public class SavingsAccount : BankAccount
{
    public SavingsAccount(string accountNumber, string accountHolder, decimal initialBalance)
        : base(accountNumber, accountHolder, initialBalance)
    {
    }

    // Implement the abstract method for SavingsAccount
    public override void Withdraw(decimal amount)
    {
        if (Balance >= amount)
        {
            Balance -= amount;
            Console.WriteLine($"Withdrawn: ${amount}, Current Balance: ${Balance}");
        }
        else
        {
            Console.WriteLine("Insufficient balance!");
        }
    }
}

public class CurrentAccount : BankAccount
{
    public CurrentAccount(string accountNumber, string accountHolder, decimal initialBalance)
        : base(accountNumber, accountHolder, initialBalance)
    {
    }

    // Implement the abstract method for CurrentAccount
    public override void Withdraw(decimal amount)
    {
        if (Balance - amount >= -500) // Allow overdraft up to -$500
        {
            Balance -= amount;
            Console.WriteLine($"Withdrawn: ${amount}, Current Balance: ${Balance}");
        }
        else
        {
            Console.WriteLine("Insufficient balance! Overdraft limit reached.");
        }
    }
}

// Step 3: Main program
public class Program
{
    public static void Main()
    {
        // Create instances of specific account classes
        BankAccount savingsAccount = new SavingsAccount("SAV123", "Shekh Ali", 1000);
        BankAccount currentAccount = new CurrentAccount("CUR456", "Roman", 900);

        // Perform transactions on accounts
        savingsAccount.DisplayAccountInfo();
        savingsAccount.Deposit(500);
        savingsAccount.Withdraw(200);

        Console.WriteLine();

        currentAccount.DisplayAccountInfo();
        currentAccount.Deposit(200);
        currentAccount.Withdraw(600);
    }
}

Output:

Account Number: SAV123
Account Holder: Shekh Ali
Balance: $1000
Deposited: $500, Current Balance: $1500
Withdrawn: $200, Current Balance: $1300

Account Number: CUR456
Account Holder: Roman
Balance: $900
Deposited: $200, Current Balance: $1100
Withdrawn: $600, Current Balance: $500

Code Explanation:

  1. We define an abstract class BankAccount with properties AccountNumber, AccountHolder, and Balance, which are common to all types of bank accounts. We also declare an abstract method called Withdraw() for withdrawing money. Since the withdrawal behavior varies for different account types, we leave it abstract to be implemented by derived classes.
  2. We create two specific account classes, SavingsAccount and CurrentAccount, that inherit from the BankAccount abstract class. Each concrete class provides its specific implementation for the Withdraw() method, representing the withdrawal behavior for a savings account and a checking account.
  3. In the main program, we create instances of SavingsAccount and CurrentAccount using the abstract class BankAccount. This demonstrates how we can work with different types of bank accounts through the abstract class without knowing their specific implementations.

References-MSDN: Abstract Class

FAQs – C# Abstract Class

Q: What is a C# abstract class?

A C# abstract class is a class that cannot be instantiated directly but serves as a blueprint for other classes. It provides a common structure and functionality that other classes can inherit and extend.

Q: How do abstract classes achieve abstraction?

Abstract classes achieve abstraction by hiding the implementation details and showing only the essential functionalities. They contain abstract members (methods, properties, or events) without implementations, leaving the exact behavior to be defined by the derived classes.

Q: Can we create an instance of an abstract class?

No, we cannot create an instance of an abstract class directly using the new keyword. Abstract classes are meant to be inherited by other classes and used as a base for creating objects of derived classes.

Q: What is an abstract method in C#?

An abstract method in C# is a method declared in an abstract class without a body. It provides a signature and method name but lacks implementation details. Derived classes must override and implement the abstract method.

Q: When should I use an abstract class?

You should use an abstract class when you want to provide a common structure and functionality to a group of related classes while leaving some specific behaviors to be defined by the subclasses. It helps promote code reusability and enforce consistency across derived classes.

Q: Can an abstract class contain concrete methods?

Yes, an abstract class can contain both abstract methods (without implementation) and concrete methods (with implementation). Concrete methods in an abstract class provide default behavior that can be used by the derived classes.

Q: Can we create an abstract class without any abstract members?

Yes, you can create an abstract class without any abstract members. An abstract class can contain only concrete methods if you want to provide a common implementation for the derived classes.

Recommended Articles:

Shekh Ali
4 2 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments