Sign in to follow this  

Enums don't have their own variables?

This topic is 476 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, so I'm making a Tictactoe game (on libGDX) and thought of having Enums for the grid's 'mark state', and also thought "why not store the grid's position on that enum too?" Thinking about it now doing that's kinda silly I know; but it seems I discovered something about enums I didn't knew, and googling about I couldn't find anything on it reassuring my discovery, so I come here :)

 

So first I made this Enum:

public enum Seed {
	EMPTY, CROSS, CIRCLE;
	
	Vector2 position;
}

Then went ahead and implemented the initialization code and loop (deleted unrelevant code):

public class Game extends ApplicationAdapter {	
		
	Seed[][] playBoard;
	
	@Override
	public void create () {		
		playBoard = new Seed[3][3];
		buildPlayBoard();
	}
	
	public void buildPlayBoard() {
		for(int i = 0; i < 3; i++) {
			for(int j = 0; j < 3; j++) {
				playBoard[i][j] = Seed.EMPTY;
				playBoard[i][j].position = new Vector2();
				
				switch(i) {
				case 0: playBoard[i][j].position.x = BoardRenderer.firstColumn; break;
				case 1: playBoard[i][j].position.x = BoardRenderer.secondColumn; break;
				case 2: playBoard[i][j].position.x = BoardRenderer.thirdColumn; break;
				}
				
				switch(j) {
				case 0: playBoard[i][j].position.y = BoardRenderer.firstRow; break;
				case 1: playBoard[i][j].position.y = BoardRenderer.secondRow; break;
				case 2: playBoard[i][j].position.y = BoardRenderer.thirdRow; break;
				}				
			}
		}
	}
}

But I found that all my enum's(grid) position vectors would end up being (thirdColumn, thirdRow) no matter what... Debugging I first thought making new Vector2 was resseting my vectors, but obviously that wasn't the case, nor the switch statements. That's when I found out the 'position' vector on the Seed class was being treated as static or something, storing all positions as the last iteration [2][2]...

 

I then verified this by making a Panel class with their own Seed and 'position' variable...

public class Panel {
	Vector2 position;
	Seed seed;
	
	public Panel() {
		seed = Seed.EMPTY;
		position = new Vector2();
	}
}

Founding that this way my initialization method would work as intended with the SAME algorithm (with playBoard being a Panel[3][3]):

public void buildPlayBoard() {
	for(int i = 0; i < 3; i++) {
		for(int j = 0; j < 3; j++) {
			playBoard[i][j] = new Panel();
				
			switch(i) {
			case 0: playBoard[i][j].position.x = BoardRenderer.firstColumn; break;
			case 1: playBoard[i][j].position.x = BoardRenderer.secondColumn; break;
			case 2: playBoard[i][j].position.x = BoardRenderer.thirdColumn; break;
			}
				
			switch(j) {
			case 0: playBoard[i][j].position.y = BoardRenderer.firstRow; break;
			case 1: playBoard[i][j].position.y = BoardRenderer.secondRow; break;
			case 2: playBoard[i][j].position.y = BoardRenderer.thirdRow; break;
			}				
		}
        }
}

And with the Seed enum being just... an enum :P

public enum Seed {
	EMPTY, CROSS, CIRCLE;
}

So am I being st**id or do Enums actually behave static-ish with their variables?

Share this post


Link to post
Share on other sites

 

Well see all the methods in those examples are returns and the variables final and stuff.

It even says it: "special data type that enables for a variable to be a set of predefined constants", so yeah, no point in wanting it to have instance variables ahaha.

Btw I found another answer here now: http://stackoverflow.com/questions/26326291/how-does-java-support-instance-variables-of-java-enum-constants Of course AFTER making this post  -_-  -_-

 

 

But anyway I'll take this chance for some more shameless reasurring; in this rendering loop:

for(int i = 0; i < 3; i++) {
	for(int j = 0; j < 3; j++) {
		switch(game.playBoard[i][j].seed) {
		case CROSS:
			renderX(game.playBoard[i][j].position); break;
		case CIRCLE:
			renderO(game.playBoard[i][j].position); break;
		default:
			break;
		}
	}
}

Should I'll be using switch on a per-step method ( since this will be called on libGDX's render() ), or a simple if else would be (far) more efficient?

Share this post


Link to post
Share on other sites

Yeah dont store stuff in enums. They're basically singletons. Language guaranteed singletons.

 

Putting logic in enums is fair, but it becomes messy if you use the same enum for different things. Although it does opens up to further refactoring (you put too much login in an enum, then it probably means you must make a separate class for that).

 

Furthermore, enums are restrictive. switch over enums is fast, but limited. It can only handle the cases it explicitly states. No more, no less. Thus when you introduce a new value for a given enum, all of the switch cases in which you use said enum become outdated since you have to add the new case.

 

So, often, its better to extract that functionality out of the enum into a different class, and reverse the responsibility. ie, no longer having object X do Y or Z depending on an enum value, but rather have a new class do whatever it knows how to do (Y or Z), at X's request.

Share this post


Link to post
Share on other sites

Hmm, this is very interesting.  I haven't really touched Java since 1.5/1.6, so call it ten years ago.  It would never occur to me to do something like this in C#, which is my daily workhorse - I don't think you can assign non-integrals to an enum in C#, but I can't say I've wanted to do that.  I do sometimes add extension methods to an enum type, but those need to be defined in an external, static class in C#.

 

This seems like a situation where the right thing to do is create a struct or class to group the vector and the enum value for the board cell.

Share this post


Link to post
Share on other sites
 It would never occur to me to do something like this in C#

Because you can't. In C#, enums are a thin typesafe shim over integer types. In Java they're full blown objects. Not only can you put fields and methods in enums, but you can also have different overrides in each value of a particular enum. They cant extend classes because they already implicitly extend Enum, but they can implement interfaces.

Edited by TheChubu

Share this post


Link to post
Share on other sites

Wow thanks for the answers guys, I appreciate it :D

 

So yeah gotcha, not use enums as classes basically. That nailed particularly with the explanation on how C# treats enums too.

 

 

[...] no longer having object X do Y or Z depending on an enum value, but rather have a new class do whatever it knows how to do (Y or Z), at X's request.

 

I think I understand this, but I'm not deciding what to render on my enum, but on a BoardRenderer class' method:

public void render() { // BoardRenderer's render method called in main Game class render() after an input update and stuff
		shapeRend.begin(ShapeType.Line);
		
		renderBoard(); // Here I render the board outlines...
		
		for(int i = 0; i < 3; i++) {
			for(int j = 0; j < 3; j++) {
				if(game.playBoard[i][j].seed == Seed.CROSS) // This right here, being 'game' a reference to my Game class where I make the array matrix
					renderX(game.playBoard[i][j].position); // I pass the cell position
				else if(game.playBoard[i][j].seed == Seed.CIRCLE)
					renderO(game.playBoard[i][j].position); // I pass the cell position
			}
		}
		
		shapeRend.end();
	}

You mean having this loop on my game class and calling BoardRenderer.renderX / renderO directly from there after looping through my seeds? I mean I would still need to use conditionals and wouldn't I be breaking the Renderer class 'encapsulation'?

 

Sorry if I don't get it right away, I'm fairly new to actual programming after having somewhat learned the basics of Java :P

Share this post


Link to post
Share on other sites

This topic is 476 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this