Timon de Groot
Timon de Groot

Reputation: 8153

How to make extendible ArrayList?

At the moment I'm working on a game and things are going pretty good. What keeps me busy at the moment, is making a mob spawner which spawns mobs in a certain area.

The big problem is right now, I'm not really sure how to keep track of all the mobs being spawned by the spawner, as there are different inheritances of mobs.

This is my MobSpawner class:

public class MobSpawner {

    protected List<Mob> mobs;

    protected Level level;

    protected int timer = 0;
    protected int spawnTime = 0;
    protected int maxMobs = 0;

    public MobSpawner(Level level) {
        this.level = level;
    }

}

And this is my RoachSpawner class:

public class RoachSpawner extends MobSpawner {

    public RoachSpawner(Level level) {
        super(level);
        mobs = new ArrayList<Roach>(); // Roach is an extension of Mob
    }

}

This is not gonna work because the List and ArrayList must be of the same type.

So the question is, does anyone have any other ideas how to do this?

Thanks in advance!

Upvotes: 1

Views: 114

Answers (2)

Jason C
Jason C

Reputation: 40315

I'm presuming that Roach extends Mob.

You can use an ArrayList<Mob> to hold Roaches. So:

public RoachSpawner(Level level) {
    super(level);
    mobs = new ArrayList<Mob>();
}

And if you just use ArrayList<Mob> in all the implementations, you can allocate it in the base instead (assuming ArrayList is always the container you want -- if you want to use other List types see kwah's answer and have subclasses create list):

public class MobSpawner {

    protected final List<Mob> mobs = new ArrayList<Mob>();

    ...

}

And just have the subclasses use the base's list.

Instantiating the list in the base class and making it final has a bonus side-effect of letting you state the following invariants (presuming you don't violate them with reflection or anything):

  • A MobSpawner will never have a null mobs, and
  • mobs will reference the same object throughout the entire lifetime of a MobSpawner.

Being able to make those assumptions can possibly simplify some of your logic in other places.

Making it final also enforces, at compile time, that you're not inadvertently replacing it with another list somewhere.

Upvotes: 3

kwah
kwah

Reputation: 1149

If you are not already doing so, try taking advantage of supertypes.

In the same way that you can declare a variable to be a List and then instantiate it to be an ArrayList, try saying your List contains Character items and then fill it with specific implementations of the Characters (eg List<Character> is instantiated as ArrayList<Mob> and ArrayList<Roach>).

public abstract class Character { }

public class Mob extends Character { }
public class Roach extends Character { }



public class Spawner {
    protected List<? extends Character> characters;
    protected Level level;
    protected int timer = 0;
    protected int spawnTime = 0;
    protected int maxCharacters = 0;

    public Spawner(Level level) {
        this.level = level;
    }

}



public class RoachSpawner extends Spawner {
    public RoachSpawner(Level level) {
        super(level);
        mobs = new ArrayList<Roach>();
    }

}

public class MobSpawner extends Spawner {
    public RoachSpawner(Level level) {
        super(level);
        mobs = new ArrayList<Mob>();
    }

}

Upvotes: 1

Related Questions