Okay, 'cause Guy asked...
One of the common mistakes made when one starts in object-oriented programming is to solve everything with subclasses. Since OO is all about adding functionality by subclassing, why not?
Well, as it turns out, subclassing is a heavy-weight operation; not in terms of CPU cycles but in terms of impact on the design of your code. It should really only be done as the last resort if none of the other approaches is appropriate.
To make up an example appropriate to many of us...let's say you are doing an RPG game and you decide that your mob class hierarchy will reflect the race of the mob:
Okay, fine enough. Now after implementing lots of race-related code, it becomes time to start handling character classes. Well, since subclassing is what it's all about, we'll do it through subclasses:
After copying and pasting code back and forth for a couple of days, I'm happy. Until I realize that I forgot to add one important thing to the shaman classes, so I go to each race and add that item to the shaman subclass.
Then I realize that I forgot all about players! Well, I decide that I want players to be recognizable from their type, so I'd like to have a mob/player class.
But wait a minute, this game allows players to be any race. So now I need to implement:
Worse, I need to copy all the class-specific code to create mob/player/goblin/shaman and the like. And each time I make some change, I have to make it in six or more places.
Now is the time when people think "I know! I need multiple inheritance! That way I can create three class hierarchies and combine them into one!"
Well I don't have space here to get into this religious war. Some people love multiple-inheritance; people who have always worked without it (like me) tend to find it a massively complicated solution that seriously obfuscates code. (Again, a rant I'll only go into if someone wants to hear it...) Fortunately, the designers of Byond were too smart to fall into this trap.
And finally we get to the simple, clean solution, which of course means it is practically impossible to implement in C++, but a breeze in Byond: delegation.
In a single-inheritance world like Byond, you need to decide very carefully what your class structure will be. The class structure should be based on the most important, core, least malleable aspect of what you are doing. Everything else should be handled by delegation (and a cousin, protocols). For RPG games, I'm still leaning toward the mob classes being based on race (but I might change my mind as I get to really coding that stuff).
So again you have:
Now, when you decide to add character classes you realize that each race might able able to be each class. And you realize that combat AI will be based on class (a wizard's approach to combat being very different from a warrior's). So each mob class will have a class delegate to handle, among other things, combat. In your mob code you create a combat method:
characterClassDelegate // This object is responsible for class-related behavior.
// I don't know ahead of time what class of object this is, but I don't care as long as it responds to the typical characterClassDelegate methods.
// As a mob I don't know what to do here.
// If I have a characterClassDelegate, it knows how to fight based on what character class I am.
// Uh oh I don't have a character class.
// Run away!
The important thing here is that the mob class has NO IDEA how you are handling character class stuff. It has no concept of wizards or warriors or whatever, it doesn't care if you have
or if you have one big object that does everything:
All it knows is that if it has a characterClassDelegate, it can ask it to take care of certain operations. In other words, it "delegates" some responsibilities to the delegate and doesn't have to worry about it after that.
Typically in such cases, you will check if a delegate exists and if that delegate has the particular method you need. If it doesn't, then you have default behavior.
Using this approach, you keep your mob hierarchy simple, and you keep all functionality related to a particular character class centralized. That is, all wizard functionality can be in one place, without being spread around among a bunch of mob classes.
Probably many people stumble across this method without even realizing they are officially using "delegation", because it just makes sense.
Hopefully this description is useful. Now off to some actual Byond programming!
Jun 25 2000, 6:19 am