Generic Constraint Attribute: Associated Mismatch

I am working on a project with an extensive tree of common inheritances and dependencies. Go to edit to see a better example. The basics look something like this:

class A { ... } class B { ... } class C extends B { ... } class D<T extends B> extends A { ... } class StringMap<T extends A> { HashMap<String, T> _elements; ... } 

So now I'm going to write a class that contains a specific type of StringMap .

 class X { StringMap<D<C>> _thing = new StringMap<D<C>>; ... } 

So far, everything is working fine. D<C> is actually a very long name, and a particular combination will be displayed very often in other parts of the code, so I decided the class for a particular combination to be more clear and have a shorter name.

 class DC extends D<C> { } //and go to update X class X { StringMap<D<C>> _thing = new StringMap<D<C>>(); //still works fine StringMap<DC> _thing = new StringMap<DC>(); //error ... } 

Strike>

Eclipse gives an error

Associated mismatch: DC type is not a valid replacement for the limited parameter <T extends A> type StringMap<T>

So the question is, why doesn't this just work? DC does nothing but extend the D<C> and echo constructors. Why StringMap see DC as excellent when it is only a child class of something other than it?

EDIT:
Well, I reworked the example to be closer to what I'm actually doing. I tested it and it causes an error. What I'm doing here uses a generic type to ensure that clone() returns the correct class for those who implement it in the inheritance tree. Then in subclasses I use B<T extends B<T>> to ensure that subclasses of B are passed in subclass of B as a generic type T

 public abstract class Undoable<T> implements Comparable<T> { public abstract T clone(); public abstract void updateFields(T modified); } abstract public class A<T extends A<T, U>, U extends Comparable<U>> extends Undoable<T> { abstract U getKey(); @Override public int compareTo(T element) { return getKey().compareTo(element.getKey()); } } public class B<T extends B<T>> extends A<T, String> { @Override public T clone() { // TODO Auto-generated method stub return null; } @Override public void updateFields(T modified) { // TODO Auto-generated method stub } @Override String getKey() { // TODO Auto-generated method stub return null; } } public class C extends B<C> { } public class D<T extends B<T>> extends A<D<T>, String> { @Override String getKey() { // TODO Auto-generated method stub return null; } @Override public D<T> clone() { // TODO Auto-generated method stub return null; } @Override public void updateFields(D<T> modified) { // TODO Auto-generated method stub } } public class DC extends D<C> { } public class StringMap<T extends Undoable<T>> { HashMap<String, T> _elements; } public class Main { public static void main(String[] args) { StringMap<D<C>> _thing = new StringMap<D<C>>(); //works StringMap<DC> _thing1 = new StringMap<DC>(); //error //Bound mismatch: The type DC is not a valid substitute for //the bounded parameter <T extends Undoable<T>> of the type StringMap<T> } } 
+6
java generics type-erasure restriction
source share
4 answers

You must be doing something wrong, because the following works just fine:

 import java.util.HashMap; public class Q { class A { } class B { } class C extends B { } class D<T extends B> extends A { } class StringMap<T extends A> { HashMap<String, T> _elements; } class DC extends D<C> { } //and go to update X class X { StringMap<D<C>> thing1 = new StringMap<D<C>>(); // still works fine StringMap<DC> thing2 = new StringMap<DC>(); // NO error!!! } } 

Try publishing a class that reproduces your error.

+8
source share

As already mentioned, your code is fine, although, if I can guess, you wanted to write the following line, which will actually cause an error:

 StringMap<D<C>> _thing = new StringMap<DC>; //error 

The reason is the same as the problem:

 ArrayList<Number> = new ArrayList<Integer>(); 

A parameter of a typical type set to the class when determining the type of identifier, i.e. in lvalue cannot be created, i.e. in rvalue, a type whose parameter inherits the parameter specified in lvalue, If the parameters are different, the types are not considered compatible, although intuitively they should have been (if the generics were implemented in the language a little differently).

This is a bit like ...

+4
source share

I'm not sure why you want to do this and that you want to use StringMap exactly, but changing the definition of StringMap to this will allow you to do what you did to compile:

 class StringMap<T extends Undoable<? super T>> { HashMap<String, T> _elements; } 

This means that a type T must be Undoable of any type if that type is contravariant to T (indeed, T itself). Now you can do this:

 StringMap<DC> _thing1 = new StringMap<DC>(); // no more error _thing1._elements.put("a key", new DC()); 

Having said that, this is just a theoretical exercise - I strongly recommend that you avoid using such complex inheritance hierarchies, but it is difficult to offer an alternative without full use.

I hope this helps!

+2
source share

Hmmm. Hope this is not an ancient old strike, but I am solving a problem that I also had. I noticed that in DD it should expand B or C should expand D due to the loop around A., enough to make me put a ton of effort into notifying anyone. The problem is the StringMap class, which strictly wants its own input to extend the general class, the common attribute of which should be its input.

D works because D is the same class that is specified in the extension. It's safe. D refers to oneself. D extends A, String>. Creating a StringMap with it is good because D implements Undoable>, because D extends A, String> which extends Undoable>. DC, on the other hand, must also implement Undoable, which is impossible due to its extension of only D; the solution may also be for him to implement Undoable, where a new definition of methods with DC is needed. This is the real problem you are facing. I hope this solves your problem.

My old problem:

In the class DT extends B, but then D extends A>. However, instead of returning the expected A or>, it extends A, String>. However, D does not extend B. Therefore, both A, String> and A. Since inheritance from two of the same interface with different common private classes is not implemented in Java, T must extend D. However, C does not extend D , which is the problem you are facing , which is a problem that may need to be fixed in the future.
0
source share

All Articles