I have the following class hierarchy:
public abstract class Config<T> implements Proxy<T> {
public abstract T parse();
public T get() {....}
}
public class IntegerConfig<Integer> extends Config<Integer> {
public Integer parse() {...}
}
public class LongConfig<Long> extends Config<Long> {
public Long parse() {...}
}
public class IntegerListConfig<List<Integer>> extends Config<List<Integer>> {
public List<Integer> parse() {....}
}
And so on...
I'd like to introduce a new class:
public class ConfigMutation<T> implements Proxy<T> {
public ConfigMutation(....) {
//// create a concrete implementation of Config<T> according to actual parameterized type
}
}
Essentially, I'd like to avoid repeating the entire class hierarchy of Config, and support in ConfigMutation all types that have parameterized implementations in Config class hierarchy.
Couldn't find a way to do it. (Class<T>)((ParameterizedType)getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0] obviously returns T, and not the actual type.
Also, once this problem is solved, I'd be happy if someone could suggest some factory pattern with generic types, so when I'm instantiating a Config derived class inside ConfigMutation, I wouldn't have to do it with a huge if...else block on actual type.
Thanks,
Lior
Change your ConfigMutation class to :
public class ConfigMutation<U,T extends Config<U>> implements Proxy<U> {
public ConfigMutation() {
}
}
You can then use ConfigMutation as :
ConfigMutation<Integer,IntegerConfig> mutation;
You won't be able to do something as follows which is what you want :
ConfigMutation<String,IntegerConfig> mutation;
That said, there is a change you need to make to your concrete Config implementers as well. For example, change IntegerConfig to :
public class IntegerConfig extends Config<Integer> {
public Integer parse() {...}
}
The Integer in IntegerConfig<Integer> will be considered as a type parameter and not the Integer class which is not what you want. (An IDE should give you a warning for this; The type parameter Integer is hiding the type Integer)
Related
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);
I want to override a method and replace a parameter it takes with a subclass of that parameter.
For return type there is no problem, because they are not a part of method signature and can be replaced with subclasses (called "covariant return type"). For arguments this is not working, because they are a part of signature.
So I came out with solution to use generic parameter of the same type:
public abstract class A<T extends A> {
public void loadValuesFrom(T source) {
...
}
}
public class B extends A<B> {
public void loadValuesFrom(B source) {
super.loadValuesFrom(source);
...
}
}
But the statement "public abstract class A" looks odd to me. Are there any other ways to achieve this? Any "covariant parameter type"? :-)
If it must be a parameter type, using generics is probably the best option. I'd only do a minor correction to avoid the raw type in the class declaration:
public abstract class A<T extends A<T>> {
If however you have the special case where the object being initialized needs to be freshly created, you might include creation in a method, thereby removing the need to pass that object as parameter:
public abstract class A {
public A clone() {
}
}
public class B extends A {
public B clone() {
// copy state
}
}
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.
I have the following class structure:
public class Team {
...
}
public class Event {
}
public abstract class Fixture<T extends Team> implements Event {
...
}
public abstract class Forecast<Event> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends Forecast<Fixture<? extends Team>>{
}
I am trying to model sports events of all kinds (i.e. a 'Fixture' is for a particular game between two participants play against each other, whereas another type of 'Event' may have many participants), along with predictions for the outcome of particular 'Events'. I have a generic method:
public <T> MyPrediction<Fixture<? extends Team>> getMyPrediction(Fixture<? extends Team> fixture) {
}
I want to be able to return a MyPrediction instance which has the generic type of the fixture argument, but I can't seem to do so. For example, if I do something like the following, then I get a compilation error:
SoccerFixture<EnglishSoccerTeams> soccerMatch = new ScoccerFixture<EnglishSoccerTeams>();
MyPrediction<SoccerFixture<EnglishSoccerTeams>> = getMyPrediction(soccerMatch);
I am willing to change my class structure to incorporate this feature. How can I do so?
Change the signature of getMyPrediction to
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture)
This tells the compiler that the fixture types in the argument and result are the same, allowing type-checking to pass.
Here is a complete example, with some other minor changes to get it to compile. It introduces the class Predictor to hold the getMyPrediction method and a doit method to show sample use:
public interface Team {
}
public interface Event {
}
public abstract class Fixture<T extends Team> implements Event {
}
public abstract class Forecast<T> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends
Forecast<Fixture<? extends Team>> {
}
public class SoccerFixture<T extends SoccerTeam> extends Fixture<T> {
}
public class SoccerTeam implements Team {
}
public class EnglishSoccerTeam extends SoccerTeam {
}
public class Predictor {
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture) {
return new MyPrediction<T>();
}
public void doit() {
SoccerFixture<EnglishSoccerTeam> soccerMatch = new SoccerFixture<EnglishSoccerTeam>();
MyPrediction<SoccerFixture<EnglishSoccerTeam>> myPrediction = getMyPrediction(soccerMatch);
}
}
As noted elsewhere, you might need to introduce one or more factory objects to perform meaningful work in the MyPrediction implementation.
Java's type system is not powerful enough to do directly what you propose, because of type erasure (the generic parameters are not available at runtime.
The usual solution is to create a separate EventFactory class, which you can then pass in to any method which needs to create a specific Event subtype instance.
public abstract class AbstractTool<AT extends AbstractThing> {
protected ArrayList<AT> ledger;
public AbstractTool() {
ledger = new ArrayList<AT>();
}
public AT getToolAt(int i) {
return ledger.get(i);
}
// More code Which operates on Ledger ...
}
public class Tool<AT extends AbstractThing> extends AbstractTool {
public Tool() {
super();
}
}
How do I correctly call super to pass the AT generic of Tool to the AbstractTool constructor?
It seems no matter what I pick AT to be when I declare Tool (Say, Tool<Thing>), that I always get back an AbstractThing instead of Thing. This seems to defeat the purpose of generics...
Help?
public class Tool<AT extends AbstractThing> extends AbstractTool<AT> {
In other words, if you extend or implement something with generics, remember to define the generics arguments for them.
Shouldn't it rather be
Tool<AT extends...> extends AbstractTool<AT>?
I think what you probably want is:
public abstract class AbstractTool<AT extends AbstractThing> {
protected List<AT> ledger = new ArrayList<AT>();
public AT getToolAt(int i) {
return ledger.get(i);
}
// More code Which operates on Ledger ...
}
public class Tool extends AbstractTool<Thing> {
// Tool stuff ...
}
Since Tool is a concrete class, it doesn't need to be parametrized itself. There is no need for the constructors if you initialize the List (oh and remember to program to the interface) at declaration, and because it is protected the subclasses can access it directly.