I've got generic interface Operand:
public interface Operand<T extends Operand<T>> {
T add(Operand<T> op);
T sub(Operand<T> op);
T mul(Operand<T> op);
T div(Operand<T> op);
}
which is implemented by 2 classes:
public class DoubleOperand implements Operand<DoubleOperand> {
...
}
public class RationalOperand implements Operand<RationalOperand> {
...
}
I've written "factory" interface implemented by DoubleOperandFactory and RationalOperandFactory classes:
public interface OperandFactory {
<T extends Operand<T>> Operand<T> valueOf(String s);
}
public class DoubleOperandFactory implements OperandFactory{
#Override
public Operand<DoubleOperand> valueOf(String s) { ... }
}
public class RationalOperandFactory implements OperandFactory {
#Override
public Operand<RationalOperand> valueOf(String s) { ... }
}
In my program I use an enum which objects store instance of the particular Factory:
public enum OperandType {
DOUBLE(new DoubleOperandFactory()), RATIONAL(new RationalOperandFactory());
private OperandFactory fact;
OperandType(OperandFactory fact){ this.fact = fact; }
public OperandFactory getFact() { return fact; }
}
Now I'm getting message warning "Unchecked overriding" on both factory classes, due to unchecked conversion and I'm pretty confused about this. First thing which I tried is (as it was most commonly answered here in similar topics) to replace generic method with generic factory interface, but finally it turns into impossibility to use them with the enum which should return particular factory, without <?>, as I have to create a List of operands (of generic type T extends Operand<T> for now) and fill it with the objects produced by selected factory. What would be the best way to reorganize this code?
public interface OperandFactory {
<T extends Operand<T>> Operand<T> valueOf(String s);
}
This interface does not do what you think it does.
This interface advertises that an instance of it can generate any type of operand you want. It doesn't just generate one particular kind of operand. It generates all of them.
This is not what you actually have.
What you need instead is
public interface OperandFactory<T extends Operand<T>> {
T valueOf(String s);
}
...and then to give up on the enum, because you can't have enums that have different types in them like that. That's just not a thing you're allowed to do in Java.
Related
I have a similar requirement to this question.
I would like to generify a method but restrict the types the acceptable by the generic parameter. Currently what I do is attempt to cast to the acceptable types in the method but seems cumbersome if dealing with more than 2 or 3 types.
EDIT:
The types may not be of the same base class. Apologies for not mentioning this earlier.
For this, You must have a base class so that you can do this.
public class Person {
String name;
List<Profession> professions;
int age;
}
public class Doctor {
String university;
Boolean doctorate;
public void work() {
// do work
}
}
public class Teacher {
List<Grade> grades;
float salary;
public void work() {
// do work
}
}
public class Animal<T> {
T type;
}
So, now if you want to write a method which is generic and applies to all, You can do something like this,
public void doSomething(Animal<T extends Person> human) {
human.work();
}
If the class is not of type Person, it will show a compilation error.
UPD1:
In the case, all the classes do not have a common base class. There is some functionality that makes them unique. By this, we can consider them to have a common function, which we can and should add using an interface.
Let's look at some code,
public class Human implements Growable {
public void grow() {
// human grow code
}
}
public class Plant implements Growable {
public void grow() {
// plant grow code
}
}
public class Table {
// does not grows
}
public class GrowService {
public static void grow(Growable growable) {
growable.grow();
}
}
interface Growable {
public void grow();
}
And by calling the below method, we can achieve this
// Works fine
GrowingService.grow(new Plant());
// throws compilation error
GrowingService.grow(new Table());
Java Generics allow basic wildcards such as <T> but also more specifics like
<T extends Number> which means any type T that is Number or a subclass of it or
<T super Number> which means T can be Number or any superclass of Number all the way up to Object.
I have an interface with a type parameter that allows its conversion into the same type with another type parameter. Like this:
interface Interfaze<A> {
public <B> Interfaze<B> convert(java.util.function.Function<A, B> f);
}
I now want to impose a stricter requirement on the return type: I want the convert method to only return the same type as it was called on. Like this:
class GoodInterfaze<A> implements Interfaze<A> {
public <B> Interfaze<B> convert(java.util.function.Function<A, B> f) {
// return new GoodInterfaze<B>(); // I want this to be allowed by compiler
// return new BadInterfaze<B>(); // I want this to be a compilation error
return null;
}
}
class BadInterfaze<A> implements Interfaze<A> {
public <B> Interfaze<B> convert(java.util.function.Function<A, B> f) {
// return new GoodInterfaze<B>(); // I want this to be a compilation error
// return new BadInterfaze<B>(); // I want this to be allowed by compiler
return null;
}
}
The Interfaze interface is under my control, so I can add extra type parameters to it (or its methods) when needed. Do Java generics allow for anything like this?
You can get close by doing this.
public interface Interfaze<T extends Interfaze<T>> {
T convert();
}
Then you can do
public class Main {
public static class Good implements Interfaze<Good> {
#Override
public Good convert() { return new Good(); } // Compiles
}
public static class Bad implements Interfaze<Bad> {
#Override
public Bad convert() { return new Good(); } // Doesn't compile
}
}
This idea of using recursive bounds like this is very common. I personally dislike it as it's very confusing and because it doesn't mix well with inheritance. For example, you can't make a subclass SubGood of Good that implements Interfaze<SubGood> because you can't implement the same generic interface with 2 different type arguments. It only really works if all implementing classes cannot be extended (that's why Enum<E extends Enum<E>> is ok).
i have a problem with an Interface and generic setters that i tried to solve for some hours now.
i have an interface where i want to define some getter and setter functions. the getter functions should be implemented by some abstract class since they usually shouldn't change.
the setter functions on the other hand should be overrideable multiple times by a defined class. In the case i try to describe it would be that the childClass should be able to implement 2 setFunctions with the same name and different input values
Interface TestClass {
public abstract void setSomething(List<?> value);
public abstract List<String> getSomething();
}
abstract class AbstractTestClass implements TestClass {
List<String> someData;
public List<String> getSomething() {
return someData;
}
}
class TestClassImplementation extends AbstractTestClass() {
#Override
public void setSomething(List<String> data) {
someData = data;
}
#Override
public void setSomething(List<SomeOtherType> data) {
someData = convertToStringList(data);
}
private List<String> convertToStringList(List<SomeOtherType> data) {
... do some conversion ...
return returnList;
}
}
hope this gives the idea of what i want to do. I would even prefer to implement the setSomething with the stringlist in the abstract class. But both setters must be reachable.
Thanks
You simply can't do that. Generics are not retained at runtime (google type erasure for more infos on this or just read the wikipedia page).
This means that your setSomething-methods all have the same signature, as their only parameter is of type List.
Well, you should try with generic solution:
Interface TestClass<T> { //Generic type T that you will provide when extending with actual class
public abstract void setSomething(List<T> value);
public abstract List<T> getSomething();
}
class TestClassImplementation extends AbstractTestClass<RealType> {
#Override
public void setSomething(List<RealType> data) {
someData = data;
}
}
The thing that confuses you is that the wildcard sign ? does not mean it changes any type, it just denotes an unknown type.
I have this generic interface:
public interface TjbListener<T> {
public void hearChange(T t);
}
Which I use like this:
public interface ObjectOneListener extends TjbListener<ClassOne> {
}
I would like to write an abstract generic class A which takes a generic type U as a parameter and has a method (1) which itself calls a method (2) on U. Below is my attempt U should extend (or implement maybe?) the generic TjbListener interface.
public abstract class ListenerInformer<U extends TjbListener<"what should I write here">> {
List<U> mListeners = new ArrayList<U>();
public void addListener(U u){
mListeners.add(u);
}
public void informAll("what should I write here"){
for(U u:mListeners){
u.hearChange("what should I write here");
}
}
}
One solution I thought of as I was writing this question is below, but I don't know if it's really a solution, or if it has subtle problems I don't understand:
public abstract class ListenerInformer<U extends TjbListener<T>,T> {
List<U> mListeners = new ArrayList<U>();
public void addListener(U u){
mListeners.add(u);
}
public void informAll(T t){
for(U u:mListeners){
u.hearChange(t);
}
}
}
UPDATE: BEWARE
I have just discovered that this approach is almost useless for my particular case because the same class cannot implement the same interface with different parameters. See the question linked below. This means that I cannot have one class be a listener of two different types with my (or Johanna's) solution, without using a different strategy like composition.
How to make a Java class that implements one interface with two generic types?
Your second example should work. But if it is as simple as that, then there is no need for the Generic U, because every instance of a subclass of TjbListener also is an instance of TjbListener.
You can do more simple:
public abstract class ListenerInformer<T> {
List<TjbListener<T>> mListeners = new ArrayList<TjbListener<T>>();
public void addListener(TjbListener<T> u){
mListeners.add(u);
}
public void informAll(T t){
for(TjbListener<T> u:mListeners){
u.hearChange(t);
}
}
}
That works as your code does and is easier to handle.
Two generic types is necessary if you need the final implementation type of the subclass of TjbListener as return value of parameter, for example if you have
public U informAll2(T t){
for(U u:mListeners){
u.hearChange(t);
if (...)
return u;
}
}
In this case your declaration with two generic types is correct (just I'm not sure if it is possible to declare the generic U, which depends of T, before you declare T, of if you have to declare T first, like public abstract class ListenerInformer<T, U extends TjbListener<T>> )
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.