I have one supertype defined as:
public abstract class AType<T> {
....
private T value;
private T mask;
public T getValue() {
if (isMasking())
return null;
return this.value;
}
public void setValue(T value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = value;
}
protected T getMask() {
if (!isMasking())
return null;
return this.mask;
}
protected void setMask(T mask) {
if (mask == null)
throw new IllegalArgumentException("Mask is mandatory.");
this.setMasking(true);
this.mask = mask;
}
...
}
and few subtypes like:
public class SpecType extends AType<Integer> {
...
}
these sub types specifies the unknown parameter…. i have more f.e. IPv4, Long, and so on
now i need to somehow in runtime do a dynamic cast…
i have these classes defined in enum like this:
public enum Type {
SOME_TYPE(new TypeID(0, (short) 0), OFMU16.class,
new Instantiable<AType<?>>() {
@Override
public SpecType instantiate() {
return new SpecType(new OFMatchTypeIdentifier(0, (short) 0));
}
}),...;
...
public Class<? extends AType<?>> toClass() {
return this.clazz;
}
...
}
I want do something like:
AType<?> type = SOME_TYPE.newInstance(); //this works
SOME_TYPE.toClass().cast(type).setValue(10); //this don't work
so I have to do it statically:
((SpecType) type).setValue(10);
Everything would be OK, but the user of this module will not want to look in enum and cast manually every time. This will probably make mistakes and spend a lot of time with debugging :/….
My question is how can I refactor this or how do I define structure of inheritance to allow user to cast dynamically? Is it possible?
Edit:
I am parsing packets from network. There is a lot types which differs in Vendor Type identifier and type of Value/Mask – these fields are all constant for every this combination, so i has defined it as enum constants. F.e. 20 have different only TypeID but same VendorID and all of them can be represented as Integer, next 10 differ in VendorID And TypeID but all of them can be represented as Short and so on.
It’s still not clear why you should have to cast at all. As soon as
SOME_TYPEis written into your sourcecode OR the type of setsetValuemethod is hardcoded (in your exampleintorInteger) you don’t need runtime checking – you need compile time checking.So I suppose the following snippet is how your API users should code:
I have stripped down your example to the bare minimum which is required to understand the Generics part:
The key part is: Don’t use an
enum, because anenumcannot have type parameters. You can use a plaininterfaceinstead like the next snippet. Each reference in the interface points to a factory. Each factory knows a) the abstract type and b) the concrete type. To make Generics happy you have to glue a) and b) together with? extends X.Cleanup: Must your user look into the interface: Yes, he must in any case, because he must know which is the appropriate type for
setValue1. NO solution can circumvent this. Although Eclipse might help you and your users a little bit: Inmainjust typeTypes.SOME_TYPE_1.instantiate();then go to the start of the line, hit Ctrl2 + L (“Assign to loccal variable”) and Eclipse replaces theAType<String> instantiate =part for you.1If your users don’t know the right type for the
setValuemethod, then you are asking the wrong question. In that case you should have asked something like “How to design a Generic safe conversion facility?”.