Two ways to avoid a large amount of similar sub-classes

A question on stackoverflow, which I’ve edited:

Is it bad OOP practice to subclass MANY classes from a base class?

Is it is bad practice in Object Oriented Design to subclass multiple classes from a single base class?

Say for instance you are designing a game and you have several different monsters you might come across. The approach I would take is to have a base abstract class for just a general monster object and then subclass all of the specific types of monsters from the base class using a new class.

One of my instructors told me that you shouldn't rely on inheritance in this case because the number of monsters will continue to grow and grow and the number of classes will increase to a point where it is hard to keep track of all of them and thus you will have to recompile the program with every new class added in the future.

My answer:

If monsters are very similar, in that the only differences are (for example) their name, how much damage they impart, what color they are, etc., then these differences which can be reflected in a field (in values), may make sub-classing unnecessary.

If, however, you have monsters that are fundamentally different from others, such that it is necessary to have very different methods and logic, and more specifically, differences that cannot be reflected in fields, then a sub-class SpecialMonster may be necessary.

But again, even SpecialMonster may not need to be sub-classed by individual monster types, as it’s fields may be enough to distinguish between them.

While it’s legal to have a million sub-classes of specific monster types, you don’t want to take care of all that duplicate code when it could simply be expressed in the fields of new Monster instances, such as

new Monster("Goob", WakeTime.NOCTURNAL, 35, new Weapon[]{sword, hammer, knittingNeedle});
new Monster("Mister Mxyzptlk", WakeTime.ANYTIME, 71, new Weapon[]{sword, mindMeld, cardboardCutter});

There is an alternative, where you do have a lot of classes, but you don’t impose them onto your users, and you don’t clutter up your API/JavaDoc with them. If your Monster happens to be an abstract class

public abstract class Monster  {
   private final String name;
   ...
   public Monster(String name, int default_damage, WakeTime wake_time, Weapon[] weapons)  {
      this.name = name;
      ...
   }
   public String getName()  {
      return  name;
   }
   ...
   public abstract int getDamage(int hit_strength);
}

Then you could have a Monster convenience creator like this:

/**
  <P>Convenience functions for creating new monsters of a specific type.</P>
 **/
public class NewMonsterOfType  {
  private NewMonsterOfType()  {
     throw  new IllegalStateException("Do not instantiate.");
  }
  /**
     <P>Creates a new monster that is nocturnal, has 35-default-damage, and whose weapens are: sword, hammer, knittingNeedle.</P>
   **/
  public static final GOOB = new GoobMonster();
  /**
     <P>Creates a new monster that can be awake at any time, has 71-default-damage, and whose weapens are: sword, mindMeld, cardboardCutter.</P>
   **/
  public static final MISTER_MXYZPTLK = new MisterMxyzptlkMonster();
}
class GoobMonster extends Monster  {
  public GoobMonster()  {
     super("Goob", WakeTime.NOCTURNAL, 35, new Weapon[]{sword, hammer, knittingNeedle});
  }
   public int getDamage(int hit_strength)  {
     return  (hit_strength < 70) ? getDefaultDamage() : (getDefaultDamage() * 2);
  }
}
class MisterMxyzptlkMonster extends Monster  {
  public GoobMonster()  {
     super("Mister Mxyzptlk", WakeTime.ANYTIME, 71, new Weapon[]{sword, mindMeld, cardboardCutter});
  }
   public int getDamage(int hit_strength)  {
     return  (hit_strength < 160) ? getDefaultDamage() + 10 : (getDefaultDamage() * 3);
  }
}

In order for these private (actually package-protected) classes to not show up in you JavaDoc, you need to set its access to something either protected or public.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s