Introduction
Abstract classes and methods are key features in C# that enable you to define classes and methods with incomplete implementation. An abstract class cannot be instantiated, and it serves as a blueprint for other classes. Abstract methods are declared in abstract classes and must be implemented by derived classes. These features promote a clear and consistent design while enabling polymorphism and code reuse.
Abstract Classes
An abstract class is a class that cannot be instantiated and often includes one or more abstract methods. Abstract classes can also contain fully implemented methods, fields, properties, and constructors.
Syntax
public abstract class AbstractClassName
{
// Abstract method (must be implemented by derived classes)
public abstract void AbstractMethod();
// Non-abstract method (can be inherited or overridden)
public void RegularMethod()
{
// Method body
}
}
Example
Let’s consider an example where we define an abstract class Shape
and its derived classes Circle
and Rectangle
.
using System;
namespace AbstractClassExample
{
// Abstract base class
public abstract class Shape
{
public abstract double GetArea(); // Abstract method
public void Display()
{
Console.WriteLine("Displaying the shape.");
}
}
// Derived class
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
// Implementing the abstract method
public override double GetArea()
{
return Math.PI * Radius * Radius;
}
}
// Derived class
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
// Implementing the abstract method
public override double GetArea()
{
return Width * Height;
}
}
class Program
{
static void Main(string[] args)
{
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
Console.WriteLine($"Circle Area: {circle.GetArea()}");
circle.Display();
Console.WriteLine($"Rectangle Area: {rectangle.GetArea()}");
rectangle.Display();
}
}
}
Output
Circle Area: 78.53981633974483
Displaying the shape.
Rectangle Area: 24
Displaying the shape.
Abstract Methods
An abstract method is a method declared in an abstract class that does not have an implementation. Derived classes must provide the implementation for abstract methods.
Syntax
public abstract class AbstractClassName
{
// Abstract method (must be implemented by derived classes)
public abstract void AbstractMethod();
}
Example
Consider the abstract class Animal
with an abstract method MakeSound
and its derived classes Dog
and Cat
.
using System;
namespace AbstractMethodExample
{
// Abstract base class
public abstract class Animal
{
public abstract void MakeSound(); // Abstract method
}
// Derived class
public class Dog : Animal
{
// Implementing the abstract method
public override void MakeSound()
{
Console.WriteLine("Dog barks.");
}
}
// Derived class
public class Cat : Animal
{
// Implementing the abstract method
public override void MakeSound()
{
Console.WriteLine("Cat meows.");
}
}
class Program
{
static void Main(string[] args)
{
Animal dog = new Dog();
Animal cat = new Cat();
dog.MakeSound(); // Outputs: Dog barks.
cat.MakeSound(); // Outputs: Cat meows.
}
}
}
Output
Dog barks.
Cat meows.
Key Points
- Abstract Classes: Abstract classes cannot be instantiated and are intended to be base classes for other classes.
- Abstract Methods: Abstract methods do not have a body and must be implemented in derived classes.
- Non-Abstract Members: Abstract classes can include non-abstract methods, fields, properties, and constructors.
- Implementation Requirement: Derived classes must implement all abstract methods of the base class.
- Polymorphism: Abstract classes and methods are used to achieve polymorphism in C#.
Real-World Example
Consider a real-world example of a banking system where different types of accounts share common features but have their own specific behaviors.
Abstract Class Example
using System;
namespace BankingExample
{
// Abstract base class
public abstract class BankAccount
{
public string AccountNumber { get; set; }
public double Balance { get; set; }
public BankAccount(string accountNumber, double initialBalance)
{
AccountNumber = accountNumber;
Balance = initialBalance;
}
// Abstract method to be implemented by derived classes
public abstract void CalculateInterest();
// Non-abstract method
public void Deposit(double amount)
{
Balance += amount;
Console.WriteLine($"Deposited {amount}. New balance: {Balance}");
}
// Non-abstract method
public void Withdraw(double amount)
{
if (amount <= Balance)
{
Balance -= amount;
Console.WriteLine($"Withdrew {amount}. New balance: {Balance}");
}
else
{
Console.WriteLine("Insufficient balance.");
}
}
}
// Derived class
public class SavingsAccount : BankAccount
{
public SavingsAccount(string accountNumber, double initialBalance)
: base(accountNumber, initialBalance)
{
}
// Implementing the abstract method
public override void CalculateInterest()
{
double interest = Balance * 0.04;
Balance += interest;
Console.WriteLine($"Interest added. New balance: {Balance}");
}
}
// Derived class
public class CheckingAccount : BankAccount
{
public CheckingAccount(string accountNumber, double initialBalance)
: base(accountNumber, initialBalance)
{
}
// Implementing the abstract method
public override void CalculateInterest()
{
// No interest for checking accounts
Console.WriteLine("No interest for checking accounts.");
}
}
class Program
{
static void Main(string[] args)
{
BankAccount savings = new SavingsAccount("S123", 1000);
savings.CalculateInterest(); // Outputs: Interest added. New balance: 1040
savings.Deposit(500);
savings.Withdraw(300);
BankAccount checking = new CheckingAccount("C123", 1000);
checking.CalculateInterest(); // Outputs: No interest for checking accounts.
checking.Deposit(500);
checking.Withdraw(300);
}
}
}
Output
Interest added. New balance: 1040
Deposited 500. New balance: 1540
Withdrew 300. New balance: 1240
No interest for checking accounts.
Deposited 500. New balance: 1500
Withdrew 300. New balance: 1200
Benefits of Abstract Classes and Methods
- Code Reusability: Abstract classes provide a way to define common behavior for derived classes, promoting code reuse.
- Polymorphism: Abstract classes and methods enable polymorphic behavior, allowing different implementations of the same method in different derived classes.
- Design Consistency: Abstract classes enforce a consistent design by requiring derived classes to implement specific methods.
- Modularity: Abstract classes help in breaking down complex systems into more manageable components.
Conclusion
Abstract classes and methods in C# are powerful tools for designing robust and maintainable object-oriented applications. By defining common behaviors in abstract classes and enforcing implementation in derived classes, you can create a consistent and flexible architecture. Understanding how to use abstract classes and methods effectively is crucial for developing complex software systems.