ID:194650
 
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:

mob/goblin

mob/orc

mob/halfling


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:

mob/goblin/shaman
mob/goblin/warrior

mob/orc/shaman
mob/orc/warrior

mob/halfling/shaman
mob/halfling/warrior

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:

mob/player/goblin

mob/player/orc

mob/player/halfling

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:

mob/goblin
mob/orc
mob/halfling

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:


mob
var
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.

proc
engageInCombat(mob/attacker)
// 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.
if (characterClassDelegate)
characterClassDelegate.handleCombat(mob/attacker)
else
// Uh oh I don't have a character class.
// Run away!
walk_rand(src)


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

characterclass/wizard
characterclass/warrior

or if you have one big object that does everything:

allCharacterClassesInOne

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!
Thanks for the info... it was quite informative! Hopefully one day there will be a "Forum Digest" or something so this can get a fresh distribution to future BYOND programmers.

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.

That's another rant I'd be willing to hear whenever you have the time. :)

In response to Guy T. (#1)
That's another rant I'd be willing to hear whenever you have the time. :)

Yep, yep, me too!
In response to Spuzzum (#2)
On 6/26/00 3:17 pm Spuzzum wrote:
That's another rant I'd be willing to hear whenever you have the time. :)

I want to hear a rant about how the Red Sox are better than the Yankees, if that's okay.

Z
In response to Zilal (#3)
On 6/26/00 3:44 pm Zilal wrote:
I want to hear a rant about how the Red Sox are better than the Yankees, if that's okay.

Z

Ask Tom to rant about the NBA, NBC and the Lakers sometime.
In response to Air Mapster (#4)
Ask Tom to rant about the NBA, NBC and the Lakers sometime.

Yep, Californians have complexes, that's for sure =)
In response to Zilal (#3)
On 6/26/00 3:44 pm Zilal wrote:
On 6/26/00 3:17 pm Spuzzum wrote:
That's another rant I'd be willing to hear whenever you have the time. :)

I want to hear a rant about how the Red Sox are better than the Yankees, if that's okay.

Z


Unfortunately I'm totally sports-illiterate, or I'm sure I could comply.

Multiple-inheritance rant to come later this week...(really the anti-C++ rant...)
In response to Spuzzum (#5)
On 6/26/00 6:10 pm Spuzzum wrote:
Ask Tom to rant about the NBA, NBC and the Lakers sometime.

Yep, Californians have complexes, that's for sure =)

Yeah, and since I brought up the subject of basketball, we can't dunk either.

<font size="-1">(Tom H. is the dark haired, white shirted fellow for those with fast connections who may be curious)</font>