tags:

views:

350

answers:

2

Hi.

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 kommune);
}

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 overriden?

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>
+2  A: 

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> 
Bozho
Thank you, this seemed to work. However, maybe you could please make me understand why this solution worked and not mine.
Shervin
@Shervin: because in your original design, the method specified by the interface is a generic method, and your abstract class's attempt to `@Override` it isn't one.
polygenelubricants
A: 

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.

polygenelubricants
the problem isn't the `@Override` annotation. What you are telling him to do is to hide the generic parameter from the class by introducing another one with the same name on the method. (Eclipse gives "The type parameter E is hiding the type E")
Bozho
Historically, I always write `@Override` instead of "override" to remind myself (and others) to always use the annotation. I realize that it causes confusion here. It should be clearer now. You're right about the hiding part; I don't think it's a big deal personally.
polygenelubricants
using `T` instead of `E` for the method would be better, but the whole "design" still feels wrong.
Bozho
Name hiding is fine in proper contexts, e.g. `this.kommune = kommune;` in above code. The reason why I prefer name hiding here instead of introducing a new type parameter `T` is because the two have the same exact bounds. If that isn't the case, then of course a new name that doesn't hide an established name for a different type would be best.
polygenelubricants
Okay, I took everyone's suggestion and went to discuss the problem in more general terms, and discussed the differences between the two possible solutions.
polygenelubricants