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
overridefor theAttackmethod. -
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
newkeyword on it. - The Purpose: To provide a shared “Identity” and shared “Data” (like
HealthorName) 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.");
}
}