Reputation: 1895
Let's say I am making a game of chess. Would it be more effective to have a base class of Piece()? With sub-classes for each type of piece.
Or, an enum
enum Piece{
King,
Queen,
Knight,
etc;
}
It also brings me onto a common problem I have when refining data.
GameObjects
Piece extends GameObjects
Should I stop here and declare the objects with their individual properties?
Piece King = new Piece("King",5,10); //just made up values, no significance.
Or refine it further and have:
King extends Piece
and then handle King Pieces in a polymorphic way:
Piece king = new King("King,5,10);
thanks
Upvotes: 2
Views: 139
Reputation: 4571
The main distinction is that the set of sub-classes is open-ended: you or other people who use your code can create new sub-classes without breaking old code. Enums are the opposite: other people cannot add new items to your enum and even you, the maintainer of the code, cannot add new enum constants without double-checking every single switch-case statement.
So, use enums if you do not expect new items to be added to the set. Use sub-classes otherwise. This does not mean that sub-classes are better: if you know the set of options to be closed-ended then you should NOT use sub-classes. If you do, you will find yourself writing if (... instanceof ...)
chains!
If with enums you find yourself adding new case
s to your switch
statements (or you can anticipate that) then switch to sub-classes. And if with sub-classes, you find yourself writing instanceof
chains, then switch to enums.
Upvotes: 0
Reputation: 425128
Use an enum when there are a limited and defined number if instances.
In this case, clearly there are a defined number of pieces, so use an enum.
Note that enums can have methods just like a regular class, so enums don't have to be just "values", they can do stuff.
I would not try to cram too much into your enum, and in fact I would name it PieceType
to make it clear what it represents, and perhaps have a class Piece
which is an instance of a piece that has a PieceType
, a location (board square) and a color.
Upvotes: 0
Reputation: 5673
It depends on how you want to structure the logic of your game, but it probably makes sense to define common behavior (methods) and attributes (fields) in an abstract Piece
class and then have each subtype implement abstract methods (or override default methods) and set values of inherited fields based on the ways that they vary. Maybe something like:
public abstract class Piece {
protected int value;
public int getValue() {
return value;
}
public abstract boolean isValidMove(String move);
public void move(String move) {
//common logic here
doMove(move);
}
protected abstract void doMove(String move);
}
public class King extends Piece {
public King() {
this.value = 20;
}
public boolean isValidMove(String move) {
//specific king logic here
}
protected void doMove(String move) {
//more specific king logic
}
}
This would allow you to use polymorphism to define various pieces with a common Piece
API, while the important differences are handled by each concrete type.
Piece king = new King();
//...
if(king.isValidMove(move)) king.move(move);
Enums allow you to create a set of optimized singleton instances of a common type, which can also define behavior, but they don't support overriding/implementing type-specific behavior very well because you end up having to check which enum the current instance when implementing variations. You would also end up with a problem of only having a single KING
or PAWN
instance when you really need multiples of those for a game (one white king and one black king, 8 white pawns and 8 black pawns).
public enum Piece {
KING(20),
PAWN(1);
private int value;
private Piece(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public boolean isValidMove(String move) {
switch(this) {
case KING:
//king specific logic
break;
case PAWN:
//pawn specific logic
break;
}
}
public void move(String move) {
if(this == KING) {
//king specific logic
} else if(this == PAWN) {
//pawn specific logic
}
}
}
So an enum probably wouldn't work very well in this scenario.
Upvotes: 1