Here is a figure showing the class hierarchy that I've dreamed up; examine it and see if it makes sense to you. Anything in this world is considered a Thing; a Thing has a name, a description, and may contain other Things. Things can be Rooms or Occupants. Rooms can have connections (north, south, etc). There are two kinds of Occupants, Items and Creatures. Items are things like keys and tables. Creatures can be either Players or Monsters. By "Monster" I mean the technical role-playing game definition: a Monster is anything that does actions on its own that is not a player. I've intentionally not used the word "Object" here, because we might have other objects in other packages that aren't Things.
In some sense this class hierarchy is more than we need at first (I'm not planning to implement Monsters right now), but this gives us room to grow into. Future versions might expand this further - for example, perhaps there should be types Door and Key that are extensions of Item.
So, if we know the hierarchy of types, how will the packages holding these types be organized? In Ada, types are placed in packages, and they don't need to match one-for-one. You can declare more than one type in a package, and you can use child packages to group them in special ways. However, unless there's some reason to do otherwise, the "simple" way is usually best: create a package for each tagged type. As a naming convention I use the plural for the package and the singular for the type, so tagged type "Occupant" is in package "Occupants". Each package will need to "with" the package of its parent. So we'll have packages named Things, Rooms, Occupants, Items, Creatures, Monsters, and Players.
Now that we know what packages to create, how do we define the types inside them? Well, Thing and all its descendants must be tagged types, since we have inheritance. All of the type definitions for the children Room, Occupant, and so on will probably look like this:
type X is new PARENT with private;
Ah, but how do I define the "root" of this hierarchy (in this case type Thing)? Although we don't need it right away, we probably want to be able to cause special things to happen when some objects are created or destroyed. That sounds like we need a "controlled" type, which would let us do that. However, we probably don't need to be able to assign between them, so we should probably create type Thing as new version of the "Limited_Controlled" type. Type Thing is not something you'd instantiate directly; instead, you'd create instances of its children. Thus Thing should be an abstract type; by declaring it abstract, people won't be able to create an instance of it. Here's the definition of Thing (which we'll place in package Things):
type Thing is abstract new Limited_Controlled with private;
There's a key rule of thumb that underlies some of these decisions: never expose in a package specification more than you have to. For example, notice that I've chosen to say "with private" everywhere. That means that the actual implementation of these types is hidden in the private part of the package specification and can't be used directly by its users. That means we'll be able to change the implementation later without impacting users.
Is a Player a member of the class of Things?
|Go back to the previous section||Skip to the next section||Go up to lesson 18 outline|
David A. Wheeler (firstname.lastname@example.org)
The master copy of this file is at
The master copy of this file is at "http://www.adahome.com/Tutorials/Lovelace/s18s2.htm".