Introduction


Abstract class An Abstract Class is a restricted class that acts as a “Partial Blueprint.” It represents a generic concept (like “Enemy” or “Shape”) that is too broad to exist on its own.

An Abstract Method is a contractual requirement placed inside an abstract class. It is a method that has a signature but no body (no code).

“An Abstract Class is a blueprint you can’t build yet, and an Abstract Method is a ‘To-Do’ list that the parent forces the child to finish.”

The Problem: Writing “Fake” code When you have a normal Enemy class, C# forces you to write code inside every method. But for a generic enemy, you don’t actually know what the code should be!

Bad code (Normal class)

public class Enemy 
{
    public virtual void Attack() 
    {
        // PROBLEM: What do I put here? 
        // I don't know how a "Generic" enemy attacks.
        // So I write "fake" code just to make the computer happy
        Console.WriteLine("???"); 
    }
}

The Disaster: A new developer joins your team to add a ShadowAssassin. This enemy is supposed to do 100 damage from the dark.

  • They create the class: public class ShadowAssassin : Enemy { }.

  • They get busy fixing a UI bug and forget to write the override for the Attack method.

  • The Result: The compiler is perfectly happy. The code builds. The game ships.

Runtime Bug When the player reaches the final level, they encounter the ShadowAssassin. Instead of a terrifying 100-damage strike, the assassin walks up and does a nothing.

Why? Because the developer forgot the override, and the computer silently fell back to the Parent’s “Fake Code.”

The Problem: The game didn’t crash. There was no error. You just have a “broken” game that feels cheap to the player. You now have to hunt through 50 enemy files to find out who forgot an override.

The Solution: Abstract Class Enforcement

By switching to abstract, you move the responsibility from the “Human Memory” to the Compiler.

public abstract class Enemy 
{
    // NO "FAKE" CODE. NO BODY.
    // This is a MANDATORY REQUIREMENT for every child.
    public abstract void Attack(); 
}

Now, when that developer creates ShadowAssassin, the compiler stops them instantly.

  • The Error: “ShadowAssassin does not implement inherited abstract member Enemy.Attack()”
  • The Outcome: The developer cannot even run the game until they write the 100-damage logic.

Abstract Class vs Abstract Method

An Abstract Class is a class-level setting. Its main job is to act as a Shield that prevents “Generic” objects from existing.

  • The Rule: You cannot use the new keyword on it.
  • The Purpose: To provide a shared “Identity” and shared “Data” (like Health or Name) that all children will use.
// This is the SHIELD. 
// It prevents: Enemy e = new Enemy();
public abstract class Enemy 
{
    public int Health = 100; // All enemies have health
    public string Name;
}

An Abstract Method is a method-level setting. Its main job is to act as a Contract that forces children to work.

  • The Rule: It has no body { }. It ends with a semicolon ;
  • The Purpose: To ensure that every child has a specific behavior, even if the parent doesn’t know how that behavior works yet.
public abstract class Enemy 
{
    // This is the CONTRACT.
    // It forces: Every child MUST write an Attack logic.
    public abstract void Attack(); 
}
public abstract class Enemy // THE SHIELD: No generic enemies allowed!
{
    public string Type; // SHARED DATA

    public abstract void Attack(); // THE CONTRACT: You MUST define this!
}

public class Mage : Enemy 
{
    // Signing the contract
    public override void Attack() 
    {
        Console.WriteLine("Fireball!");
    }
}

With constructor

public abstract class Enemy 
{
    public string Name;
    public int Health;

    // CONSTRUCTOR: Forces anyone building a child to provide these values
    public Enemy(string name, int health)
    {
        this.Name = name;
        this.Health = health;
        Console.WriteLine($"{Name} has joined the battlefield!");
    }

    public abstract void Attack(); 
}
public class Mage : Enemy
{
    // The Mage constructor takes the info and sends it UP to the Enemy constructor
    public Mage(string mageName) : base(mageName, 50) 
    {
        // Mage specific setup can go here
    }

    public override void Attack()
    {
        Console.WriteLine($"{Name} casts Fireball!");
    }
}
// --- THE GAME START ---
class Program
{
    static void Main()
    {
        Mage myMage = new Mage("Gandalf the Grey");
        // 2. The Wrong Way (The Safety Check):
        // Enemy ghost = new Enemy("Ghost", 10); 
        //  COMPILER ERROR: Cannot create an instance of the abstract class 'Enemy'
        
        // 3. Using the Contract:
        myMage.Attack(); 
        
        Console.WriteLine($"Status: {myMage.Name} has {myMage.Health} HP.");
    }
}