Best way to implement character classes

Started by
16 comments, last by Sneftel 17 years ago
Quote:Original post by Telastyn
Quote:Original post by Programmer16
Quote:Original post by RDragon1
and get rid of that silly C prefix. Csoldier is a lot less readable than Soldier.


You really should try to be helpful with your replies. If somebody likes prefixing their class names with 'C' then who are you to say they shouldn't?


Someone who would be more helpful if they didn't have to spend more time and effort ignoring useless prefixing.


My point is that it's a preference and it's rude to push yours onto other people. It takes no more time than if you have a namespace tacked on there.

Also, it's not entirely useless. It does help keep names open for use as variable names (Texture, Vector, Point, Device, etc.)

Btw, do you think he really would have been more helpful seeing as he wasted oh so much time and effort getting by that one little letter yet he still didn't post anything helpful?

An even better question is why was his coding preferences called into question when they had nothing to do with his problem?

[Edited by - Programmer16 on April 21, 2007 1:09:57 AM]
Advertisement
Quote:Original post by Programmer16

My point is that it's a preference and it's rude to push yours onto other people. It takes no more time than if you have a namespace tacked on there.


And my point is that it's not just a preference. I could prefer to only ever use single letter variable names. Is that a preference? Sure. It's also exceptionally annoying to myself and anyone else using the code later.

It does take no more time than if you have a namespace, but the namespace also relays information. C prefixing is redundant.

Quote:
Also, it's not entirely useless. It does help keep names open for use as variable names (Texture, Vector, Point, Device, etc.)


So does the convention exemplified by Sneftel's example. That scheme also is (imo) more readable and (in my experience) a lot more prevalent. Consistency across a codebase is quite helpful.

Quote:
Btw, do you think he really would have been more helpful seeing as he wasted oh so much time and effort getting by that one little letter yet he still didn't post anything helpful?


No, not really.

Quote:
An even better question is why was his coding preferences called into question when they had nothing to do with his problem?


Why do people caution against char *, hand made linked lists, explicitly sized arrays, MSVC 6.0.... Just because a preference doesn't cause the problem in question doesn't mean it isn't a problem.

Don't get me wrong... redundant variable/typename prefixing isn't nearly as problematic, but having increased readability and consistency in a codebase only helps.

Wow, this subject was certainly enlightening, especially the code example... But I now, as with all knowledge, there are some questions that arose:
1. Let's consider multiple race (for instance) - If I got a few races, say elf, human and gnome. Say we still have the Race class, what's better - Inherit those 3 from race and use Race (With maybe some "race specific" code abstracted using some kind of a callback) or create the Modification of race and use them as attributes?
More specifically, what's better in this case - Inheriting Race:
(Sources in python, because it's a lot faster and clearer than CPP IMHO)
class Race():...class Orc():...class HalfOrc(Race, Orc):...class HalfCow(Race):...#etc


...or using changing race's attributes:
Race():    str = 5    accuracy = 5Orc = Race()Orc.str = 10Orc.Accuracy = 3



2. How about using introspection (Like python's) for making such stuff? Something like dir()-ing the class to get its special powers? Will this be as fast? Becuase it will allow a bit more maneuvering power, and extensibility.

3. If someone has the will to elaborate - Why is multiple inheritance isn't as good a solution?

Thanks a lot, this thread is very informative.
Mikle
Mikle
Quote:Original post by Mikle3
1. Let's consider multiple race (for instance) - If I got a few races, say elf, human and gnome. Say we still have the Race class, what's better - Inherit those 3 from race and use Race (With maybe some "race specific" code abstracted using some kind of a callback) or create the Modification of race and use them as attributes?

There's surprisingly little difference; as long as the race never changes and you don't do RTTI, there's actually no outward difference. Again, though, prefer composition to inheritance. If only some numbers are different, then inheritance isn't even worth considering. If there's actually code which is different, then use a Strategy pattern if possible. Basically, you want to make the classes which do the actual inheritance as teeny as possible.

Quote:2. How about using introspection (Like python's) for making such stuff? Something like dir()-ing the class to get its special powers? Will this be as fast? Becuase it will allow a bit more maneuvering power, and extensibility.
That's a trickier question. I wouldn't use introspection like that, but it might be reasonable to have a Race consist of a series of Modifier objects which modify the attributes of the character and/or add special powers. This is something where the Right Way is much less clear.

Quote:3. If someone has the will to elaborate - Why is multiple inheritance isn't as good a solution?

Because it's not the right way to think about it. If there's an elf mage, you think about him as a guy who is an elf and who also is a mage. The fact of his elfhood and the fact of his magehood are not inextricably linked. In your code, this would manifest itself as an explosion of classes; you'd have to have a class for every potential race/character class combination, and you'd need some ugly factory stuff to actually pick one.
Mikle3,

IMO inheritance is used to group things that have different functionality into one system. A good example I think would be an event from animation system. All events get triggered the same way (after a certain time in the animation), but when executed they do different things (one plays a sound, on does damage to adjacent enemies). The common thing is that they are all triggered the same way. If in using multiple inheritance your ancestors are not orthogonal; then your derived classes no longer override, they compose. Composition by inheritance makes the base classes dependent on one another. For example if both base classes had health functionality, then the derived class would have 2 kinds of health which are really the same thing.

When you ask yourself what is common to an Orc, an Elf, a Catapult and a soldier what do you come up with? What is different about an Orc than a Half Orc?
Don't shoot! I'm with the science team.....
Sneftel: regarding multiple inheritance, what if you could do it like this:

Character* tom_the_elf_wizard = new Elf&&Wizard

the && operator would create an anonymous class at compile time. Do you think that it would be good? Assume that all inheritance is automatically virtual so that there is no dreaded diamond problem.
Quote:Original post by Mikle3
2. How about using introspection (Like python's) for making such stuff? Something like dir()-ing the class to get its special powers? Will this be as fast? Becuase it will allow a bit more maneuvering power, and extensibility.

I don't think introspection really helps here, at least not in python. You could more easily use a dict to hold the special powers.
Quote:Original post by Glak
Sneftel: regarding multiple inheritance, what if you could do it like this:

Character* tom_the_elf_wizard = new Elf&&Wizard

If you have a character creation screen where the player selects race and class then you'll need explicit code for every combination. If you use composition instead of multiple inheritance, then you only need code for each race and each class, instead of every combination. For your syntax to really be an improvement, you'd also need to have run-time class creation (which is possible in some languages), but the resulting system would still be more complicated.
Quote:Original post by Glak
Sneftel: regarding multiple inheritance, what if you could do it like this:

Character* tom_the_elf_wizard = new Elf&&Wizard

the && operator would create an anonymous class at compile time. Do you think that it would be good? Assume that all inheritance is automatically virtual so that there is no dreaded diamond problem.

If that sufficed for your design, it would be proof positive that multiple inheritance was gaining you absolutely nothing, because there's nothing about ElfWizard that doesn't directly come from either Elf or Wizard. The bottom class would have an empty class body.

This topic is closed to new replies.

Advertisement