I think I finally managed to understand the concept of Interfaces in Java - by comparing it to Dungeons & Dragons. It came to me when I was on the toilet.
Classes and Objects
Lets say that “elf” is a class of creature - a type of creature. However, that’s all it is - statistics and attacks and abilities. In order to encounter one or more elves, the DM must create them into the game world, or in Java terms, instantiate them.
ilithane = new elf();
gerynale = new elf();
Ilithane and Gerynale here are two standard elves as detailed in the Monster Manual. In Java terms, they’re objects of the class “elf”.
An “elf” has many attributes, such as Strength, Dexterity and so forth. These are its variables. It also has things it can do - attacks, special attacks and so forth. These are its methods.
Lets say you want to create a “drow”, which is a subrace of elf. Drow is a subclass of elf.
public class drow extends elf
"Drow" has all the properties of "elf", except in cases where class "Drow" has added or changed something that "elf " has (such as gaining spell resistance).
Elf itself is a subclass of humanoid, which is a subclass of creature.
A spell like Charm Person works on any humanoid. Since class “elf” is a subclass of humanoid, an elf is considered to be a humanoid for anything that works on humanoids. This is polymorphism.
An abstract class is something like “humanoid” or “creature” which cannot be instantiated because objects of its type can’t exist. You can’t encounter just a “humanoid” - it has to be a specific type of humanoid, like an elf or a dwarf. Thus things like “creature”, “humanoid” exist only to be superclasses to other types of creature and cannot be instantiated.
A creature cannot simultaneously be of two types - it cannot be both an elf and a human, or both a humanoid and an undead. A half-elf is considered either a subtype of humanoid, or of elf. A human who becomes a vampire is considered type undead, not humanoid. The reason for this is type conflicts. If a vampire were humanoid and undead at the same time, he would be simultaneously vulnerable to charm person for being a humanoid, and immune to it for being undead.
An interface is thus analogous to a template in D&D, such as half-dragon or vampire. Templates are abstract, in that you can’t actually encounter a “zombie”, at least not in 3.5th edition any more - you have to encounter a human zombie, an elf zombie, or whatever.
public class humanZombie extends human implements zombie
Finally, you can add multiple templates to a monster.
public class erranisdVol extends elf implements lich, halfDragon
So by playing with D&D I’m actually refreshing my OOP skills….
Elf (and Half Elf) should both implement the interface IElf. Drow implements it by inheriting Elf, and Half Elves must implement it themselves. Thus, a sword that works only for an Elf is in fact usable only by an object that implements IElf.
just as Dwarves should implement IDwarf, etc etc. This allows proper extension and flexibility.
it all breaks apart when you realise that you have to create a new class for every combination of templates you’re using.
Java fails, try Lua or Perl.
Not until you realize that Elf should just be a particular instance of the Race class
That’s just too awesome! Gratz on grabbing onto the concepts! I’m working on creating a character generator as a way of honing my OOD skills. I have to agree with Andy: you’d end up with literally hundreds of classes. I’m currently looking at the Decorator or Factory pattern to see if those might be a better way to go.
@Andy - you’re breaking the rules of the game. There ain’t no such concept as an IElf - that should be your red-light that your model is wrong.
@prgmrgirl - the state pattern is what you want. There’s no reason to treat race as an immutable, think Polymorph* spells. It also makes it trivial to create arbitary combinations of two or more races, and also handles transforms into zombie or lich forms.
@OP - sort of but not quite. Think about the information you put a character sheet. Everything you fill in is a variable. Note that this includes the race of the character, i.e. race is just a field in the character object.
Um, you picked a bad example — if “vampire” and “humanoid” contain mutually exclusive attributes, then “humanoid” and “undead” have been implemented wrong, since a vampire dragon and a vampire human still retain certain features of their original type.
Comments for this article are closed.