Creating multiple subclass objects - java

I'm trying to achieve a 'wave' of enemies through a for loop. Basically when a wave object is called it accepts an int that sets the number of enemies in the wave. Each enemy has it's own class that is a subclass of 'Enemy'. What I'm stuck on is how I can go about passing in a second parameter in the wave constructor to set which enemy subclass is created eg 25 'Orcs' created or 13 'Trolls' in one method. Any help will be greatly appreciated.

It sounds like you want to create a static factory method of the Enemy class that creates new Enemy objects based on parameter. Something like:
// EnemyType is an enum
public static Enemy createEnemy(EnemyType enemyType) {
switch (enemyType) {
case BASIC_MONSTER:
return new BasicMonster();
case ORC:
return new Orc();
case TROLL:
return new Troll();
case ..... // etc...
}
}
Note, I would use something cleaner for the parameter such as an enum, not an int so as to be sure that the parameter passed in is correct. Otherwise you risk having a nonsense int such as -24232 being passed in.

You can use an Enum
public enum EnemyType {
ORC{
#override
public Enemy create() {
return new Orc();
}
},
TROLL{
#override
public Enemy create() {
return new Troll();
}
}...etc;
public abstract Enemy create();
}
Then pass the relevant enum into your wave method:
public Collection<Enemy> createWave(final int num, final EnemyType enemyType) {
final Collection<Enemy> enemies = new ArrayList<>(num);
for(int i=0;i<num;i++) {
enemies.put(enemyType.create());
}
return enemies;
}
If you have lots of differenet enemy types consider a generic factory
public interface EmemyFactory<E extends Enemy> {
E create();
}
Then create an implementation for each enemy type and store them in the enum instead
public enum EnemyType {
ORC(new OrcFactory()),
TROLL(new TrollFactory()),
...etc;
private final EnemyFactory enemyFactory;
public EnemyType(final EnemyFactory enemyFactory) {
this.enemyFactory = enemyFactory;
}
public Enemy create() {
return enemyFactory.create();
}
}
And last and least you could use a little reflection, assuming your Enemies have a noargs constructor:
public Collection<Enemy> createWave(final int num, final Class<? extends Enemy> enemyClass) {
final Collection<Enemy> enemies = new ArrayList<>(num);
for(int i=0;i<num;i++) {
enemies.put(enemyClass.newInstance());
}
return enemies;
}
This is messy and prone to runtime errors however...

Related

Java subclass with different method parameters

I am trying to make a simulation that simulates simple creatures and carnivorous creatures.
I have a class called creature and a subclass called carnCreature. I have a method in creature called eat, that takes in a one type of object, but I need the eat method in the carnCreature class to take in a list of creatures. I tried naming the method the same as it is named in the creature class, but when I try to call it, java doesn't accept the updated parameters.
package simulationObjects;
import java.awt.Color;
import java.util.List;
import java.util.Random;
import java.lang.Math.*;
public class Creature {
public int x;
public int y;
public int maxTilesX;
public int maxTilesY;
public Color color;
public float health = 50;
public int life = 0;
public Creature (int x, int y, Color color, int maxTilesX, int maxTilesY) {
this.x = x;
this.y = y;
this.color = color;
this.maxTilesX = maxTilesX;
this.maxTilesY = maxTilesY;
}
public void update(Tile tile) {
eat(tile);
life++;
health-=1;
}
public void eat(Tile currentTile) {
if (currentTile.color == this.color) {
health += 3;
currentTile.color = Color.GRAY;
}
}
public boolean isCarnivore() {
return false;
}
}
package simulationObjects;
import java.awt.Color;
import java.util.List;
public class CarnCreature extends Creature{
private static final boolean CANABOLIC = false;
public CarnCreature(int x, int y, Color color, int maxTilesX, int maxTilesY) {
super(x, y, color, maxTilesX, maxTilesY);
// TODO Auto-generated constructor stub
}
public void update(List<Creature> creatures) {
eat(creatures);
life++;
health-=1;
}
public void eat(List<Creature> creatures) {
for (Creature creature : creatures) {
if (CANABOLIC) {
if (creature.color == this.color) {
health += 3;
creature.health = 0;
}
} else {
if (creature.color == this.color && creature.isCarnivore() == false) {
health += 3;
creature.health = 0;
}
}
}
}
public boolean isCarnivore() {
return true;
}
}
The eat function is being called later like this:
for (Creature creature : creatures) {
if (creature.isCarnivore()) {
creature.upadte(creatures);
} else {
creature.update(tiles.get(creature.x).get(creature.y));
}
}
I am trying to store the creatures and the carnCreatures in the same list, "creatures." Is this the problem, and do I need to store them in separate lists?
Thanks
You have a two options:
Once you know if the creature is carnivore cast it and access the method
Create a method with the same "signature", that is, same name AND arguments.
The second option is the more elegant. Using the "magic" of polymorphism each class will have its method called and you won't need to check the class with the isCarnivore() method. But you will need to get the list of creatures from the tile.
The isCarnivore() test will not spare you to cast to the subclass type as you manipulate as declared type the Creature the base class :
for (Creature creature : creatures) {
if (creature.isCarnivore()) {
((CarnCreature)creature).update(creatures);
} else {
creature.update(tiles.get(creature.x).get(creature.y));
}
}
So the isCarnivore() appear helpless as if (instanceof CarnCreature) would have the same effect and consequences.
Is this the problem, and do I need to store them in separate lists?
It would be better as you don't want manipulate them in an uniform way.
Using the base class to group them in a unique List make your task harder.
But in fact you have a deeper issue. Here eat() is not a overrided method but an overloaded method in the subclass. Same thing for update().
It means that in both cases the two methods are defined in the subclass.
Such a design will not allow to benefit from a polymorphism feature because you want to invoke the first method on the base class instance and invoke the overloaded method on the subclass instance.
In terms of concept, a carnivore creature IS not a creature. Their type of behavior is very different : one consumes a thing (a tile) and the other consumes a very different thing (a list of creature).
To benefit from polymorphism you should re-design the base class and the subclass to override the methods and not overload them. But as you pass really different types in the parameters, you are stuck.
So in your case I think that I would not even create a inheritancy relation between theses classes.

There is no available constructor in the superclass (Java)

I have one super class, which called game that. It looks like this:
import java.util.ArrayList;
public class Game {
private ArrayList<Enemy> enemies = new ArrayList<Enemy>();
private ArrayList<Tower> towers = new ArrayList<Tower>();
private int corridorLength;
private int currentPosition = 0;
public Game(int corridorLength){
this.corridorLength = corridorLength;
}
public void addTower(int damage,int timeStep){
this.towers.add(new Tower(damage,timeStep)); // Add tower with
current position corrdor length
}
public void addEnemy(int health, int speed){
this.enemies.add(new Enemy(health,speed));
}
public void advance(){
this.currentPosition = this.currentPosition + 1;
if(this.currentPosition == this.corridorLength){
System.out.println("Game Over");
}
}
public void printDamage(){
System.out.println(this.towers.get(this.currentPosition));
}
}
The main focus is on the public void addTower(int, int)
So, I have a subclass called Tower:
public class Tower extends Game {
public Tower(int damage, int timeStep){
super.addTower(damage,timeStep);
}
public void getDamage(){
super.printDamage();
}
}
And subclass of the Tower subclass called Catapult:
public class Catapult extends Tower {
public Catapult(){
super(5,3);
}
}
I am new to Java and can't see what am I doing wrong here. Why do I need a default constructor for the Tower in the Game?
You need to explicitly declare default constructor in Game class.
public Game (){}
Since, Object instantiation chained to Object class during that, it will call its super class constructor. You have explicitly declared arg-constructor in Game, so default constructor won't be added automatically.

What is the best way to initialise static members before constructing objects in Java?

I am currently in the process of refactoring the code I wrote for a text/console version of the Mastermind board game. I am a bit stuck with how to best approach improving this section my GameLogic class.
public GameLogic(GameSettings gameSettings)
{
// ..other stuff..
// initialise static members
Board.setTotalRows(gameSettings.getNumOfGuesses());
Board.setTotalColums(gameSettings.getCodeLength());
// InputBoard and OutputBoard extends the abstract class Board
inputBoard = new InputBoard();
outputBoard = new OutputBoard();
}
What I am trying to do is set the static values of totalRows and totalColumns in the Board class BEFORE constructing the inputBoard and outputBoard objects. The reason why I want to do this is because I need to have these values present when constructing instances extending Board (an abstract class). The reason why I am making these values static is because they should be the same across all instances extending from Board and so that I can do something like Board.getTotalColumns() throughout the application.
The reason why I think this is suspiciously bad is because it would be possible to declare inputBoard or outputBoard without first setting the static member variables and of course it would also be possible to accidentally set the values of the static member later on to any arbitrary value.
Another approach I thought of was to make the getters in GameSettings public and static so that I could do something like this instead:
public abstract class Board
{
private static final int totalColumns = GameSettings.getCodeLength();
private static final int totalRows = GameSettings.getNumOfGuesses();
// other stuff...
}
This would allow me to avoid using setters and the problems associated with using them as listed above. But wouldn't this defeat the purpose of instantiating a GameSettings object?
What do you think are better alternatives to approach this?
I am not an expert on design pattern. I would try something like below -
Board.java
abstract class Board {
private final GameSettings gameSettings;
Board(GameSettings gameSettings) {
this.gameSettings = gameSettings;
}
public int getTotalColumns() {
return gameSettings.getCodeLength();
}
public int getTotalRows() {
return gameSettings.getNumOfGuesses();
}
//Other abstract methods
}
InputBoards .java
class InputBoards extends Board {
InputBoards(GameSettings gameSettings) {
super(gameSettings);
}
}
OutputBoards .java
class OutputBoards extends Board {
OutputBoards(GameSettings gameSettings) {
super(gameSettings);
}
}
GameSettings .java
class GameSettings {
public int getCodeLength() {
//return your value;
}
public int getNumOfGuesses() {
//return your value;
}
}
Now I would do -
public GameLogic(GameSettings gameSettings) {
inputBoard = new InputBoard(gameSettings);
outputBoard = new OutputBoard(gameSettings);
}

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!
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.
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>();
}
}

Java Factory Pattern With Generics

I would like my BallUserInterfaceFactory to return an instance of a user interface that has the proper generic type. I am stuck in the example below getting the error:
Bound mismatch: The generic method getBaseballUserInterface(BASEBALL)
of type BallUserInterfaceFactory is not applicable for the arguments
(BALL). The inferred type BALL is not a valid substitute for the
bounded parameter
public class BallUserInterfaceFactory {
public static <BALL extends Ball> BallUserInterface<BALL> getUserInterface(BALL ball) {
if(ball instanceof Baseball){
return getBaseballUserInterface(ball);
}
//Other ball types go here
//Unable to create a UI for ball
return null;
}
private static <BASEBALL extends Baseball> BaseballUserInterface<BASEBALL> getBaseballUserInterface(BASEBALL ball){
return new BaseballUserInterface<BASEBALL>(ball);
}
}
I understand that it cannot guarantee that BALL is a Baseball, and so there is a parameter type mismatch on the getBaseballUserInterface method call.
If I cast the ball parameter in the getBaseballUserInterface method call, then I get the error:
Type mismatch: cannot convert from BaseballUserInterface<Baseball>
to BallUserInterface<BALL>
Because it can't guarantee that what I am returning is the same type of BALL.
My question is, what is the strategy for dealing with this situation?
(For completeness, here are the other classes required in the example)
public class Ball {
}
public class Baseball extends Ball {
}
public class BallUserInterface <BALL extends Ball> {
private BALL ball;
public BallUserInterface(BALL ball){
this.ball = ball;
}
}
public class BaseballUserInterface<BASEBALL extends Baseball> extends BallUserInterface<BASEBALL>{
public BaseballUserInterface(BASEBALL ball) {
super(ball);
}
}
This is a wrong design pattern. Rather than using one generic method and an if ladder, you should instead use overloading. Overloading eliminates the need for the if ladder and the compiler can make sure the correct method is invoked rather than having to wait till runtime.
eg.
public class BallUserInterfaceFactory {
public static BallUserInterface<Baseball> getUserInterface(
Baseball ball) {
return new BallUserInterface<Baseball>(ball);
}
public static BallUserInterface<Football> getUserInterface(
Football ball) {
return new BallUserInterface<Football>(ball);
}
}
This way you also get the added benefit of compile time errors if your code cannot create a BallUserInterface for the appropriate ball.
To avoid the if ladder you can use a technique known as double dispatch. In essence, we use the fact that the instance knows what class it belongs to and calls the appropriate factory method for us. For this to work Ball needs to have a method that returns the appropriate BallInterface.
You can either make the method abstract or provide a default implementation that throws an exception or returns null. Ball and Baseball should now look something like:
public abstract class Ball<T extends Ball<T>> {
abstract BallUserInterface<T> getBallUserInterface();
}
.
public class Baseball extends Ball<Baseball> {
#Override
BallUserInterface<Baseball> getBallUserInterface() {
return BallUserInterfaceFactory.getUserInterface(this);
}
}
To make things a little neater, it's better to make getBallUserInterface package private and provide a generic getter in BallUserInterfaceFactory. The factory can then manage additional checks like for null and any thrown exceptions. eg.
public class BallUserInterfaceFactory {
public static BallUserInterface<Baseball> getUserInterface(
Baseball ball) {
return new BallUserInterface<Baseball>(ball);
}
public static <T extends Ball<T>> BallUserInterface<T> getUserInterface(
T ball) {
return ball.getBallUserInterface();
}
}
The Visitor Pattern
As pointed out in the comments, one problem of the above is it requires the Ball classes to have knowledge of the UI, which is highly undesirable. You can, however, use the visitor pattern, which enables you to use double dispatch, but also decouples the various Ball classes and the UI.
First, the necessary visitor classes, and factory functions:
public interface Visitor<T> {
public T visit(Baseball ball);
public T visit(Football ball);
}
public class BallUserInterfaceVisitor implements Visitor<BallUserInterface<? extends Ball>> {
#Override
public BallUserInterface<Baseball> visit(Baseball ball) {
// Since we now know the ball type, we can call the appropriate factory function
return BallUserInterfaceFactory.getUserInterface(ball);
}
#Override
public BallUserInterface<Football> visit(Football ball) {
return BallUserInterfaceFactory.getUserInterface(ball);
}
}
public class BallUserInterfaceFactory {
public static BallUserInterface<? extends Ball> getUserInterface(Ball ball) {
return ball.accept(new BallUserInterfaceVisitor());
}
// other factory functions for when concrete ball type is known
}
You'll note that the visitor and the factory function have to use wildcards. This is necessary for type safety. Since you don't know what type of ball has been passed, the method cannot be sure of what UI is being returned (other than it is a ball UI).
Secondly, you need to define an abstract accept method on Ball that accepts a Visitor. Each concrete implementation of Ball must also implement this method for the visitor pattern to work correctly. The implementation looks exactly the same, but the type system ensures dispatch of the appropriate methods.
public interface Ball {
public <T> T accept(Visitor<T> visitor);
}
public class Baseball implements Ball {
#Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
Finally, a bit of code that can put all this together:
Ball baseball = new Baseball();
Ball football = new Football();
List<BallUserInterface<? extends Ball>> uiList = new ArrayList<>();
uiList.add(BallUserInterfaceFactory.getUserInterface(baseball));
uiList.add(BallUserInterfaceFactory.getUserInterface(football));
for (BallUserInterface<? extends Ball> ui : uiList) {
System.out.println(ui);
}
// Outputs:
// ui.BaseballUserInterface#37e247e2
// ui.FootballUserInterface#1f2f0ce9
This is a VERY GOOD question.
You could cast brutely
return (BallUserInterface<BALL>)getBaseballUserInterface((Baseball)ball);
The answer is theoretically flawed, since we force BASEBALL=Baseball.
It works due to erasure. Actually it depends on erasure.
I hope there is a better answer that is reification safe.
public class BaseballUserInterface extends BallUserInterface<Baseball> {
public BaseballUserInterface(Baseball ball) {
super(ball);
}
}
You are using the BallUserInterface as a result of the factory method. So, it can be hidden which concrete ball is used:
public class BallUserInterfaceFactory {
public static BallUserInterface<?> getUserInterface(Ball ball) {
if(ball instanceof Baseball){
return getBaseballUserInterface((Baseball)ball);
}
return null;
}
private static BaseballUserInterface getBaseballUserInterface(Baseball ball){
return new BaseballUserInterface(ball);
}
}
If the client is interested in the type of the ball you should offer a factory method with the concrete ball as parameter:
public static BaseballUserInterface getUserInterface(Baseball ball){
return new BaseballUserInterface(ball);
}

Categories