Type-safe way to access grouped constants

Edit: My solution is pretty useless since as quew8 pointed out you can use a private constructor.

I was wondering how to group ints in a way which would allow me to create a type-safe argument for a constructor/method. At first I didn’t think this was possible without using a switch statement with an enum, so I just grouped them in nested classes, but today I was playing with enums (I never really use them much) and found that I could do this. E.g, if you want to group OpenGL data types you can do this.


public enum DataType {
	BYTE {
		@Override
		int getType() {
			return GL_BYTE;
		}
	},
	SHORT {
		@Override
		int getType() {
			return GL_SHORT;
		}
		
	} // etc...;

	abstract int getType();
}

If you want to use it as an argument for a method, e.g uselessly returning the type from another method, you can do:


public int returnType(DataType type) {
	return type.getType();
}

And to access it you’d pass in, e.g:

returnType(DataType.BYTE);

Hopefully this could save someone a days headache. :slight_smile:

Out of interest, what do you mean that this is type safe? As opposed to what which wasn’t?

You don’t need to have an anon class per enum entry in this case…just pass in the target value to a constructor.

The function [icode]glBindBuffer(int target, int handle)[/icode] accepts an int value as the target. You could pass in 6382 which would result in an OpenGL error, as it only accepts a selection of OpenGL values, e.g GL_ARRAY_BUFFER. If you encapsulated that function in a method which only accepts those values (which is what the enum is for), then it’s effectively (though not truely) making it type-safe. You cannot pass in a value such as 6382 as it would result in a compile time error.

I thought of doing that but this approach allows you to name the entries whatever you like which is what I wanted to do. EDIT: That would also eliminate the type-safety as you could similarly pass in 343278 to the constructor which would result in a runtime error.

Oh I see. Maybe call it GLEnum safe or something rather than type safe to avoid confusion with Java generics.

And what @Roquen means is:


public enum DataType
    BYTE(GL_BYTE), 
    SHORT(GL_SHORT);
    
    private Axis(int enum) {
        this.enum = enum;
    }

    private final int enum;
    
    public int getEnum() {
        return enum;
    }
}

You can still name the entries whatever you like.

I think the problem will come when you need to be able to reuse an GLEnum in more than one function (which I’m sure you have to occasionally although I can’t think of one now). Also wouldn’t work for bit fields. Don’t get me wrong I’m not trying to pick holes, just encouraging preemptive problem solving.

Enums in java create type safety; not just generics, thus the correct term is type safe.

Doing that would just move the type-safety issue to the enum. The user could just as easily pass in 4233281 or any random int value to the enum constructor.

Enums use a private constructor. They are a fixed set of compile time values so the “user” cannot construct different ones without going into the source, changing it and recompiling. If he did that, I don’t think he’d have to look far to solve the problem.

Oh I can’t believe that I’ve never came across an enum with a private constructor before. Every enum I’ve encountered before has either had a public constructor or hasn’t declared one. My solution is pretty useless then.

[quote=“Troubleshoots,post:8,topic:45853”]
enums never have public constructors :point:

[quote=“Riven,post:9,topic:45853”]

Oops I meant package-private.

Why does private constructors make your solution useless? It works doesn’t it?

It works, but as you pointed out it has limitations in the way that it can’t be used for bit fields. It also adds unnecessary code. Therefore it’s a nobrainer to use a private constructor.