Apply generically enum member or method - java

I have an interface ServiceArgument which defines a size() promise.
public interface ServiceArgument {
public int size ();
}
Some of my enum types implement this interface
public enum StringCode implements ServiceArgument {
FOO,
BAR,
BACON,
public int size() {
return values().length;
}
}
Some of my class follow a EnumService abstract class.
public abstract class EnumService {
abstract void query (Enum<? extends ServiceArgument> e);
}
And to wrap it up, some class extends this abstract class :
public class ServiceTranslation extends EnumService implements Serializable {
/**some code and ctors and transient stuff etc **/
#Override
void query (Enum<? extends ServiceArgument> e) {
//line that matters :
if (e.ordinal() >= e.size()) {
throw InvalidStringCodeAsked();
}
}
My problem is, I can't use e.size() at the last line, because I wouldn't use FOO.size() in my example enumeration.
Is there a way to, either :
1) specialise what the query method accepts as a parameter in the concrete implementations of EnumService
2) get the concrete type of the Enum called in ServiceTranslation.query(MYSTERIOUS.ENUM), in order to be able to call ConcreteENUM.size(). or even ConcreteEnum.values().length, it's the same.
3) even filter everything that is not from the right enumerated type to throw directly a InvalidEnumeratedTypeException through method override, but i'm not familiar with multiple overriding.
4) something I didn't think of
Edit : #shmosel in the comment is right, even if I get the wrong enumeration as argument, it will never be greater than its size. No point in comparing it to its size.

How about this one?
public abstract class EnumService {
abstract <T extends Enum<T> & ServiceArgument> void query (T e);
}
public class ServiceTranslation extends EnumService implements Serializable {
#Override
<T extends Enum<T> & ServiceArgument> void query (T e) {
if (e.ordinal() >= e.size()) {
throw InvalidStringCodeAsked();
}
}
}

Related

How to satisfy parameter type Class<? extends someInterface> in java

Consider the following code
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
public interface myInterface {
int doSomething();
}
public class myInterfaceImpl implements myInterface {
public int doSomething() {
return 1;
}
}
public void callDoSomething(Class<? extends myInterface> myVar) {
System.out.println(myVar.doSomething());
}
On this line callDoSomething(new myInterfaceImpl()); I get the following error.
Error:(32, 25) java: incompatible types: com.myProject.myTest.myInterfaceImpl
cannot be converted to java.lang.Class<? extends com.myProject.myTest.myInterface>
How do I satisfy the parameter type? If only an interface is provided to me.
I want to bound the class that has an interface, but it seems like this is not avaiable to me
Class<? implements myInterace>
Edit:
The reason I want to do this is because I want to provide a custom kafka partitioner.
public Builder<K, V> withCustomPartitionner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
It looks like you want to be able to call methods on the parameter that's given. In that case, you'll want the actual instance of your interface, not the Class associated with it.
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
Class<> is used when you want to use reflection to do something with the specific class type that you're interested in:
public void outputClassInfo(Class<? extends myInterface> myClass) {
System.out.println(myClass.getName());
}
If that's what you're going for, you'll want to provide the class at compile time like this:
outputClassInfo(myInterfaceImpl.class);
Or, if you won't know which class you're dealing with until runtime, you can use reflection:
myInterface thing = getThing();
outputClassInfo(thing.getClass());
So, in the example you're providing in your edit, I'm guessing you want:
public Builder<K, V> withCustomPartitioner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
// Usage
builder
.withCustomPartitioner(FooPartitioner.class)
...
This type Class<? extends myInterface> myVar corresponds to a Class instance not to an instance of myInterface.
You generally don't pass a class as parameter (but for reflection purposes or to bypass generics erasures). So what you need as parameter is probably :
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
That you could invoke :
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
The parameter to callDoSomething shouldn't be a class. It must be an instance of that class or it's subclass.
public <T extends myInterface> void callDoSomething(T myVar) {
System.out.println(myVar.doSomething());
}
On a side note, don't name Java classes/interfaces starting with lower case.
As rightly mentioned by Andy Turner#, there is no need to use a type parameter here and you can just refer to the type as myInterface
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
You need to pass the Class not an instance.
callDoSomething(MyInterfaceImpl.class);

Java generic parameter as exact subclass?

Assuming we have a method like this:
public void foo(Class<? extends ClassBar> x) {
...
}
By modifying the generic expression;
< ? extends ClassBar >
Is it possible to ensure that ClassBar.class can't be passed in but anything extends ClassBar directly or indirectly be passed in WITHOUT throwing an exception on the runtime?
If you have only a bunch of classes extending ClassBar you can follow these two approaches.
Solution 1:
have all subclasses of ClassBar extend a custom interface (except for ClassBar itself), and change the method signature to:
public <T extends ClassBar & MyInterface> void foo(Class<T> x) {
...
}
Solution 2:
use something similar to this #AndyTurner's trick and provide instances only for specific types.
E.g:
class ClassBar {}
class ClassBarA extends ClassBar{}
class ClassBarB extends ClassBar{}
Your class containing foo:
class Foo<T extends ClassBar> {
private Foo() {} // private constructor
public static <T extends ClassBarA> Foo<T> instance(T c) {
return new Foo<T>();
}
public static <T extends ClassBarB> Foo<T> instance(T c) {
return new Foo<T>();
}
public void foo(Class<T> c) {
}
}
Only subclass of ClassBarA would be accepted in this case
Foo<ClassBarA> foo1 = Foo.instance(this.classBarA);
foo1.foo(ClassBarA.class); // pass
foo1.foo(ClassBar.class); // fail

How do I create an interface with methods that take an instance of some enum type?

I have in mind an interface which declares a method for converting a raw score from a survey to a percentile value for a particular category, where the categories are described by more than one otherwise unrelated enum types. So I started with this:
public interface NormTable<E extends Enum<E>> {
Integer percentileForRawScore(E e, int score);
}
I've then got an implementing class for, say, the Foo survey and its Subscale enum:
public class FooSubscaleNormTable implements NormTable<Subscale> {
public Integer percentileForRawScore(Subscale e, int score) {
// Implementation
}
}
And finally, a factory class for creating the appropriate concrete class:
public class NormTableFactory {
public static <E extends Enum<E>> NormTable<E> normTableForSurveyAndType(
String surveyCode, Class<E> clazz) {
if ("Foo".equals(surveyCode) && Subscale.class.equals(clazz)) {
return (NormTable<E>) new FooSubscaleNormTable();
} else {
// ...
}
}
}
I suspect the cast there is wrong, as Eclipse flags it as unchecked, though lets me carry on. The Java 1.6 compiler on the build server, however, is not happy at all and flags them as inconvertible types.
Have I got the signatures in the factory class wrong, or is my whole architecture looking suspect? I note above that the enum types are "otherwise unrelated", though they all represent categories within surveys, and could conceivably implement an interface to unify their types. Would that help?
You shouldn't use a concrete Enum class in your declaring type.
Make FooSubscaleNormTable generic as well
public class FooSubscaleNormTable<E extends Enum<E>> implements NormTable<E> {
public Integer percentileForRawScore(E e, int score) {
if(e instanceof Subscale) {
switch((Subscale) e) {
case X:
// do something
break;
}
}
// return 0;
}
}
and change your factory to
public class NormTableFactory {
public static <E extends Enum<E>> NormTable<E> normTableForSurveyAndType(
String surveyCode, Class<E> clazz) {
if ("Foo".equals(surveyCode) && Subscale.class.equals(clazz)) {
return (NormTable<E>) new FooSubscaleNormTable<E>();
} else {
// whatever else
}
}
}
Then when you invoke it, that is when you pass in your desired enum type.
NormTable<Subscale> scale = NormTableFactory.normTableForSurveyAndType("surveyCode", Subscale.class);

Java - enum wildcard

I have some problems implementing a Java feature.
I have a list of Sensors. I have different kinds of them, they all extend the base class Sensor.
I have some abstract functions in the base class, and I want these functions to take an Enum as a parameter. The problem is that the Enum is unique for each sub class, and therefore, I can't declare the Enum in the base class.
The code below has Enum as parameter. I know it's not legal syntax, but I just want to illustrate that this is where I want to have the sub class Enum as parameter.
private Vector<Sensor> sensors;
public abstract class Sensor {
public Sensor() {}
public abstract int getParam(Enum param);
public abstract void setParam(Enum param, int value);
}
public class TempSensor extends Sensor {
// Parameter names
public static enum TEMP_PARAMETERS{ PARAM_ALARM_HI, PARAM_ALARM_LO }
public TempSensor() {}
#Override
public int getParam(TEMP_PARAMETERS param) {
// Will do some stuff here
return 0;
}
#Override
public void setParam(TEMP_PARAMETERS param, int value) {
// Will do some stuff here
}
}
If the different Enums implement an interface, I can use the interface as the parameter type in the abstract methods, but then I can pass Enums that don't belong to the respective class as parameter. Is there a way to avoid that?
Looks like you want contradictory things. The whole point of using polymorphism is to take advantage of the substitution principle.
If you want to have a class hierarchy and be sure the right type is entered to the right object, you may consider using the factory pattern.
I strongly recommend against inheritance on Enums; Java doesn't handle that well.
You're on the right track. Assuming you have a marker interface called MyEnumTypeInterface, just have your different enums implement that inferface. Then use MyEnumTypeInterface as the type of the formal parameter for your methods that accept the enum. However, you need to ensure that you're getting an enum that implements MyEnumTypeInterface and not just any other class that implements MyEnumTypeInterface:
public <E extends Enum<E> & MyEnumTypeInterface>void getParam(E e)
This ensures that the formal parameter is an enum and that it implements MyEnumTypeInterface; the methed won't accept as a parameter, another class that also implements MyEnumTypeInterface.
So your classes end up looking like this:
public interface MyEnumTypeInterface {
}
public abstract class Sensor {
public Sensor() {}
public abstract <E extends Enum<E> & MyEnumTypeInterface>int getParam(E param);
public abstract <E extends Enum<E> & MyEnumTypeInterface>void setParam(E param, int value);
}
public enum TempEnum extends MyEnumTypeInterface {
PARAM_ALARM_HI,
PARAM_ALARM_LO
}
public class TempSensor extends Sensor {
public TempSensor() {}
#Override
public<E extends Enum<E> & MyEnumTypeInterface>int getParam(E param) {
return 0;
}
#Override
public <E extends Enum<E> & MyEnumTypeInterface>void setParam(E param, int value) {
// Will do some stuff here
}
}
So you want each Sensor to work a particular param type? That would mean making Sensor generic.
public abstract class Sensor<P extend Enum<P>> {
public Sensor() {}
public abstract int getParam(P param);
public abstract void setParam(P param, int value);
}
There are probably bigger problems with you design. Fixing those could remove the requirement for the get and set.

Java: generics inheritance confusion

Imagine we have following classes:
public interface MyInterface<T> {
List<T> getList(T t);
}
abstract class BaseClass<T extends Number> implements MyInterface<T> {
#Override
public List<T> getList(Number t) {
return null;
}
}
class ChildClass extends BaseClass<Integer> {
#Override
public List<Integer> getList(Integer t) {
return super.getList(t); //this doesn't compile
}
}
getList in ChildClass doesn't compile, the output is:
abstract method getList(T) in com.mypackage.MyInterface cannot be accessed directly
I can't get why BaseClass.getList method isn't overriden in ChildClass.
But what makes me completely confused is the fix that makes it compile:
class ChildClass extends BaseClass<Integer> {
#Override
public List<Integer> getList(Integer t) {
return super.getList((Number) t); //Now it compiles!
}
}
So I cast Integer to Number, and is solves the problem.
Could anyone explain what's going on in this code?
Your base class should look like:
abstract class BaseClass<T extends Number> implements MyInterface<T> {
#Override
public List<T> getList(T t) {
return null;
}
}
You weren't using T, but the Number class as a parameter.
It doesn't override because the abstract method takes a Number as a parameter and the concrete method takes an Integer. They must be the same in order to override.
You should change your abstract class implementation to take type T as a parameter.
Why isn't the superclass method defined as
public List<T> getList(T t)
?
What is going on in the imaginary class.
abstract class BaseClass<T extends Number> implements MyInterface<T> {
#Override
public List<T> getList(Number t) {
return null;
}
}
This class has one generic parameter (T) that has to extend Number class and implement the interface MyInterface
You also Try to override a method that does not exists, because this class do not extend other any class. While a class is implementing an interface there is no need to override the interface method because the are only the description.
What happen if we remove the #override annotation.
abstract class BaseClass<T extends Number> implements MyInterface<T> {
public List<T> getList(Number t) {
return null;
}
}
In this case we do not implement the method from the interface but create a new one, a this method parameter is Number that is same type as T, it will probably cause some error that class has two the same methods. (not tested by compiler)
Them implementation of this method should look like this
abstract class BaseClass<T extends Number> implements MyInterface<T> {
public List<T> getList(T t) { //Because T is allready restricted to be Number
return null;
}
}
And when You specify the type You will not have a problem to call this method when you override it
class ChildClass extends BaseClass<Integer> {
#Override
public List<Integer> getList(Integer t) {
return super.getList(t);
}
}
In advance You don have to implement it only for return null and then override it in some child class. What You can do is create class like this
abstract class BaseClass<T extends Number> implements MyInterface<T> {
private List<T> list = new ArrayList<T>(); //The way of initialization is up to You
public List<T> getList() { //Because T is allready restricted to be Number
return list;
}
}
As other colleagues pointed out the reason for issue is incorrect signature of parent method. The reason why the casting works is due to the way how compiler treats generics. It guarantees that there won't be runtime ClassCastException issues if you use generic but only if you don't do casting. As soon as you did it you actually said compiler to shut up as you know better what your type really is. However after this you potentially could get ClassCastException in runtime (not in this case I assume)

Categories

Resources