Java Generics name clash, method not correctly overridden
I have seen different questions regarding this, but I still find this topic to be very confusing.
All I want to do, is have an abstract class that implements an interface, and have a class extending this abstract class so that the hard class needs to implement getKommune()
and setKommune(Kommune kommune)
, but not the other method, because that is in the abstract class.
I have the following interface.
public interface KommuneFilter {
<E extends AbstractKommune<?>> void addKommuneFromCurrentUser(E e);
Kommune getKommune();
void setKommune(Kommune kommun开发者_Python百科e);
}
And this Abstract class
public abstract class AbstractKommune<E extends AbstractKommune<?>> implements KommuneFilter {
@PrePersist
void addKommuneFromCurrentUser(E e) {
Kommune k = e.getKommune();
}
}
And I want to use it like this
public class Person extends AbstractKommune<Person> {
private Kommune kommune;
public void setKommune(Kommune kommune) {this.kommune=kommune;}
public Kommune getKommune() {return kommune;}
}
However, I get
Name clash: The method of has the same erasure of type but does not override it
Why isn't it correctly overridden?
UPDATE
Thanks to @Bozho, the solution is this:public interface KommuneFilter<E extends AbstractKommune<?>> {
public void addKommuneFromCurrentUser(E e);
}
public abstract class AbstractKommune<E extends AbstractKommune<?>> implements KommuneFilter<E>
public class Person extends AbstractKommune<Person>
I'd suggest making the interface generic, rather than only its method:
interface KommuneFilter<E extends AbstractKommune<?>> { .. }
And then
public abstract class AbstractKommune<E extends AbstractKommune<?>>
implements KommuneFilter<E>
The reason why it's a name clash and not an override is because it isn't. The method specified by the interface is a generic method; your abstract class's attempt to override it isn't.
A more concise code that reproduces your problem is this:
interface I {
<E> void foo(E e);
}
class C<E> implements I {
public void foo(E e) { // name clash at compile time!
}
}
The problem here is that interface I
specifies that implementors must provide a generic method <E>foo
(it can be an <Integer>foo
, <Boolean>foo
, etc), but say, a C<String>
really only has foo(String)
.
One way to fix this is to make C.foo
a generic method, to properly @Override
the generic method of interface I
:
interface I {
<E> void foo(E e);
}
class C<E> implements I {
@Override public <T> void foo(T t) {
}
public static void main(String args[]) {
C<String> o = new C<String>();
o.<Integer>foo(0);
o.<Boolean>foo(false);
}
}
You can see what this does in the above code: you have a generic type C<E>
with a generic method <T>foo
(you can use E
instead of T
, but that wouldn't change anything -- it's still a generic method with its own type parameter).
Now a C<String>
also has <Integer>foo
, etc, as specified by interface I
.
If this isn't something that you need, then you probably want to make interface I<E>
generic instead:
interface I<E> {
void foo(E e);
}
class C<E> implements I<E> {
@Override public void foo(E e) {
}
}
Now the type and the method shares the same type parameter (e.g. an I<Boolean>
only has a foo(Boolean)
, a C<String>
only has a foo(String)
) which is likely what you had originally intended.
精彩评论