Introduction
An Interface is a Contract or a Blueprint of Skills. While an Abstract Class tells us what an object is (its DNA), an Interface tells us what an object can do (its Certificates). It defines a set of actions that a class must perform, but it doesn’t give the class any code to start with.
1. To Group Objects by Skill (The “Universal” Rule)
In a game , you often have completely different objects like a Player, a Zombie, and a Wooden Fence. They belong to different families, but they all share one skill: they can be hit. Instead of writing separate code for each one, an Interface allows us to treat them all as a single group of “Hittable” objects.
2. To Bypass the “One Parent” Rule
In C#, a class is only allowed to have one father (one Parent Class). This is a strict rule. However, a class can have unlimited certificates.
-
A Mage can inherit from the Enemy family…
-
…but it can also sign certificates to be Damageable, Burnable, and Talkable all at the same time.
The Problem: The One Parent Limit In C#, a class can only have ONE parent. This is called Single Inheritance. This is like a wall. Once you choose a family, you are stuck in that family.
The Scenario:
- The Player Family: High complexity, inventory, input handling.
- The Enemy Family: AI logic, patrol paths, loot tables.
The Crisis: You are coding a Sword Swing. When the sword hits something, it needs to call TakeDamage().
-
If you put
TakeDamage()only in the Enemy family, the sword cannot hurt the Player. -
If you put it in both families separately, the sword code has to be “doubled” (once for Player, once for Enemy).
As your game grows, your sword code will look like this mess:
// THE "MESSY" WAY (WITHOUT INTERFACES)
if (hitObject is Player) { (hitObject as Player).TakeDamage(); }
else if (hitObject is Enemy) { (hitObject as Enemy).TakeDamage(); }
else if (hitObject is AllyNPC) { (hitObject as AllyNPC).TakeDamage(); }
// This list will never end!
Solution The Universal Button (Interface) An Interface is a “Certificate of Capability.” It tells the sword: “I don’t care what family this object belongs to; I just care if it has the ‘Hittable’ certificate.”
We create a certificate called IDamageable.
public interface IDamageable
{
// A promise: "I know how to get hurt."
void TakeDamage(int amount);
}
Now, both the Player and the Enemy “earn” this certificate by signing the contract.
// Player: Belongs to 'Human' family, but can be damaged
public class Player : IDamageable
{
public void TakeDamage(int amount)
{
Console.WriteLine($"[PLAYER] screen shakes! UI flashes red! Lost {amount} HP.");
}
}
// Enemy: Belongs to 'AI' family, but can also be damaged
public class Enemy : IDamageable
{
public void TakeDamage(int amount)
{
Console.WriteLine($"[ENEMY] plays a 'Hurt' animation and bleeds {amount} HP.");
}
}
class Program
{
static void Main()
{
Player myHero = new Player();
Enemy myOrc = new Enemy();
Console.WriteLine("--- SWORD COLLISION SYSTEM ---");
// We use the SAME function for two DIFFERENT families!
AttackObject(myHero, 15);
AttackObject(myOrc, 25);
}
// THE MAGIC FUNCTION
// It doesn't say 'Player' or 'Enemy'. It says 'IDamageable'.
// This allows it to accept ANY object that has the certificate.
static void AttackObject(IDamageable victim, int damage)
{
victim.TakeDamage(damage);
}
}
Rules for Interface
The Rule: If the interface has 3 methods, the class must write code for all 3.
- The Penalty: If you forget even one, the compiler will throw a Red Error and the game won’t build.
The Rule: You cannot have variables like int health or string name inside an interface.
- The Logic: An interface doesn’t define who you are; it only defines what you can do.
The Rule :You don’t need to type public inside the interface itself. All methods are automatically public
- The Logic: There is no point in having a “Secret Skill” that the Game can’t call!
The Rule: You only write the name, arguments, the return type, and the semicolon ;
- The Logic: The interface doesn’t know how a Player takes damage versus an Enemy; it only knows that they both must do it.
using System;
// THE CERTIFICATE (The Skill)
public interface IDamageable
{
void TakeDamage(int amount);
}
// THE BASE FAMILY (The Data)
public abstract class Entity
{
public string Name;
public Entity(string name)
{
this.Name = name;
}
}
/*In C#, you must always list the Parent Class (the DNA) before the Interfaces (the Certificates).*/
// THE PLAYER
public class Player : Entity, IDamageable
{
public Player(string name) : base(name) { }
public void TakeDamage(int amount)
{
Console.WriteLine($"[PLAYER] {Name} UI flashes! -{amount} HP.");
}
}
// THE ENEMY
public class Enemy : Entity, IDamageable
{
public Enemy(string type) : base(type) { }
public void TakeDamage(int amount)
{
Console.WriteLine($"[ENEMY] {Name} plays hit animation! -{amount} HP.");
}
}
// THE GAME ENGINE
class Program
{
static void Main()
{
Player myHero = new Player("Aragon");
Enemy myOrc = new Enemy("Orc Warrior");
Console.WriteLine("--- FLARE ENGINE: SWORD SYSTEM ---");
AttackObject(myHero, 15);
AttackObject(myOrc, 25);
}
static void AttackObject(IDamageable victim, int damage)
{
// Now the skill is used, and the Name is printed inside the class!
victim.TakeDamage(damage);
}
}