📐 Abstract Classes: The Blueprint You Can't Build Directly
An abstract class is a class that cannot be instantiated on its own. It serves as an incomplete blueprint — it defines shared behavior and forces derived classes to fill in the blanks. You get the structure for free; the specifics are your responsibility.
Imagine the city's chief architect draws a master blueprint for all buildings. It specifies that every building must have a permit process and a description, but the exact permit type and description depend on whether it's commercial or residential. You can't construct "a blueprint" — you construct a specific building that follows the blueprint.
The abstract Keyword
Mark a class as abstract to prevent direct instantiation. Mark methods as abstract to force derived classes to provide their own implementation. Abstract methods have no body — just a signature with a semicolon.
abstract class Shape
{
public string Color;
// Abstract method — derived classes MUST implement
public abstract double Area();
// Regular method — inherited as-is
public void Describe()
{
Console.WriteLine($"A {Color} shape with area {Area()}");
}
}
class Circle : Shape
{
public double Radius;
public Circle(double radius, string color)
{
Radius = radius;
Color = color;
}
// MUST override the abstract method
public override double Area() => Math.PI * Radius * Radius;
}
// Shape s = new Shape(); // ERROR! Cannot instantiate abstract class
Circle c = new Circle(5, "Red");
c.Describe(); // "A Red shape with area 78.539..."
Abstract vs Virtual
Abstract methods have no body and must be overridden. Virtual methods have a default body and can be overridden. Use abstract when there's no sensible default; use virtual when there is.
abstract class Animal
{
public abstract void Speak(); // No default — MUST override
public virtual void Sleep() // Has default — CAN override
{
Console.WriteLine("Zzz...");
}
}
class Cat : Animal
{
public override void Speak() => Console.WriteLine("Meow!");
// Sleep() is inherited as-is — prints "Zzz..."
}
The sealed Keyword — Locking the Chain
The sealed keyword prevents a class from being inherited further, or prevents a specific method from being overridden in deeper derived classes. It's the architect saying: "This design is final. No modifications."
sealed class FinalBuilding : Building
{
// No class can inherit from FinalBuilding
}
class MiddleClass : Shape
{
public sealed override double Area() => 0; // No further override allowed
}
Template Method Pattern
Abstract classes are perfect for the Template Method design pattern: define the skeleton of an algorithm in the base class, and let derived classes fill in specific steps.
abstract class BuildingBlueprint
{
// Template method — defines the sequence
public void Construct()
{
LayFoundation();
BuildStructure(); // abstract — each building decides
GetPermits(); // abstract — each building decides
Console.WriteLine("Construction complete!");
}
private void LayFoundation()
{
Console.WriteLine("Laying foundation...");
}
protected abstract void BuildStructure();
protected abstract void GetPermits();
}
📋 Instructions
**Your Mission: Enforce the Master Blueprint!**
Create an abstract `BuildingBlueprint` and two concrete classes that follow the blueprint.
1. Create an `abstract class BuildingBlueprint`:
- A `protected string Name` field
- A constructor that takes a `string name` and stores it
- An abstract method `protected abstract string GetPermitZone()`
- A concrete method `public void Describe()` that prints `"{Type}: {Name} (permits: {zone})"` where `{Type}` comes from an abstract property/method and `{zone}` comes from `GetPermitZone()`
- An abstract method `protected abstract string GetType()`
2. Create a `CommercialBuilding` class extending `BuildingBlueprint`:
- Constructor takes a name and calls `base(name)`
- `GetType()` returns `"Commercial"`
- `GetPermitZone()` returns `"commercial zone"`
3. Create a `ResidentialBuilding` class extending `BuildingBlueprint`:
- Constructor takes a name and calls `base(name)`
- `GetType()` returns `"Residential"`
- `GetPermitZone()` returns `"residential zone"`
4. In `Main`:
- Create a `CommercialBuilding("Office Hub")` and call `Describe()`
- Create a `ResidentialBuilding("Park View")` and call `Describe()`
- Print `"Blueprint enforced for all buildings!"`
The abstract class has two abstract methods — `GetType()` and `GetPermitZone()`. The `Describe()` method in the base class calls both: `Console.WriteLine($"{GetType()}: {Name} (permits: {GetPermitZone()})");`. Note: since `System.Object` already has a `GetType()` method, you can use the `new` keyword: `protected new abstract string GetType();` — or simply name it `GetBuildingType()` to avoid the conflict.