Imagine the following class hierarchy:
interface IRules
{
void NotifyPickup(object pickedUp);
void NotifyDeath();
void NotifyDamage();
}
class CaptureTheFlag : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
if(pickedUp is Flag)
GameOver();
}
public void NotifyDeath()
{
}
public void NotifyDamage()
{
}
}
class DeathMatch : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
points++;
}
public void NotifyDeath()
{
lives--;
}
public void NotifyDamage()
{
}
}
class GameWorld
{
IRules gameMode;
public Main(IRules gameMode)
{
this.gameMode = gameMode;
}
object[] worldObjects;
public void GameLoop()
{
foreach(object obj in worldObjects)
{
// This call may have a bunch of sideeffects, like getting a pickup
// Or a player dying
// Or damage being taken
// Different game modes are interested in different events / statistics.
obj.Update();
// Stuff happens...
gameMode.NotifyDamage();
// Stuff happens...
gameMode.NotifyDeath();
}
}
}
So here I’ve got an interface which contains Notify* functions. These are callbacks. Different game modes are interested in different events of the game. It’s not really possible to access the concrete objects creating these events because they’re buried in the worldObjects array. Imagine we are adding new game modes to our game. The IRules interface will get hugely bloated, containing all the possible things a game mode may be interested in, and most calls will be stubbed! How can I prevent this?
Edit 2: Concrete example
My final solution was the C# equivalent of what xtofl posted. I created a class which stored a bunch of delegates in it. These delegates started off with default values (so they would never be null) and the different concrete IRules classes could choose to overwrite them or not. This worked better than abstract or stubbed methods because it doesn’t clog the interface with unrelated methods.
Each rule set can choose which events it wants to listen to. The game simply calls then by doing Rules.Events.ItemPickedUp();. It’s guaranteed never to be null.
Thanks to xtofl for the idea!