2010-03-30 15 views
8

Widziałem różne pytania na ten temat, ale nadal uważam ten temat za bardzo niezrozumiały.Zderzenie nazwy Java Generics, metoda niepoprawnie przesłonięta

Wszystko, co chcę zrobić, to klasa abstrakcyjna, która implementuje interfejs, i ma klasę rozszerzającą tę klasę abstrakcyjną, aby klasa twarda wymagała implementacji getKommune() i setKommune(Kommune kommune), ale nie drugiej metody, ponieważ jest to Klasa abstrakcyjna.

Mam następujący interfejs.

public interface KommuneFilter { 

    <E extends AbstractKommune<?>> void addKommuneFromCurrentUser(E e); 

    Kommune getKommune(); 

    void setKommune(Kommune kommune); 
} 

I Klasa abstrakcyjna

public abstract class AbstractKommune<E extends AbstractKommune<?>> implements KommuneFilter { 
    @PrePersist 
    void addKommuneFromCurrentUser(E e) { 
      Kommune k = e.getKommune(); 
    } 
} 

I chcę go używać jak to

public class Person extends AbstractKommune<Person> { 
     private Kommune kommune;    
     public void setKommune(Kommune kommune) {this.kommune=kommune;} 
     public Kommune getKommune() {return kommune;} 
    } 

Jednak uzyskać

Name clash: The method of has the same erasure of type but does not override it

Dlaczego nie jest on prawidłowo przesłonięte?

UPDATE

Dzięki @Bozho, rozwiązanie to:

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> 

Odpowiedz

4

Sugeruję czyniąc interfejs generycznych, a nie tylko jego metody:

interface KommuneFilter<E extends AbstractKommune<?>> { .. } 

I następnie

public abstract class AbstractKommune<E extends AbstractKommune<?>> 
    implements KommuneFilter<E> 
+0

Dziękuję, to wydawało się działać. Być może jednak mógłbyś mi pomóc zrozumieć, dlaczego to rozwiązanie działa, a nie moje. –

+0

@Shervin: ponieważ w oryginalnym projekcie metoda określona przez interfejs jest metodą ogólną, a próba klasy abstrakcyjnej "@ Override" to nie jest jedna. – polygenelubricants

2

Powodem, dla którego jest to zderzenie nazwy, a nie przesłonięcie, nie jest. Metoda określona przez interfejs jest metodą ogólną; próba pominięcia klasy abstrakcyjnej nie jest.

bardziej zwięzły kod, który reprodukuje problem jest taki:

interface I { 
    <E> void foo(E e); 
} 

class C<E> implements I { 
    public void foo(E e) { // name clash at compile time! 
    } 
} 

Problem polega na tym, że interface I określa, że ​​implementors musi dostarczyć metody rodzajowe <E>foo (może to być <Integer>foo, <Boolean>foo itp), ale powiedzmy, C<String> naprawdę ma tylko foo(String).

Jednym ze sposobów, aby to naprawić jest, aby C.foo sposób ogólny, aby prawidłowo @Override ogólną metodę 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); 
    } 
} 

można zobaczyć co to robi w powyższym kodzie: masz typ rodzajowy C<E> przy użyciu ogólnej metody <T>foo (można użyć E zamiast T, ale to niczego nie zmieniłoby - to wciąż ogólna metoda z własnym parametrem typu).

Teraz C<String> ma również <Integer>foo itp., Jak określono przez interface I.

Jeśli to nie jest coś, co trzeba, to prawdopodobnie chcesz, aby interface I<E> rodzajowy zamiast:

interface I<E> { 
    void foo(E e); 
} 

class C<E> implements I<E> { 
    @Override public void foo(E e) { 
    } 
} 

Teraz rodzaj i udziałów metoda parametru tego samego typu (np I<Boolean> ma foo(Boolean) tylko , C<String> ma tylko foo(String)), co prawdopodobnie było zamierzone.

+0

Problemem nie jest adnotacja '@ Override'. Mówi mu się, aby ukrył ogólny parametr przed klasą, wprowadzając kolejną o tej samej nazwie w metodzie. (Eclipse podaje "Parametr typu E ukrywa typ E") – Bozho

+0

Historycznie, zawsze piszę "@ Override" zamiast "override", aby przypomnieć sobie (i innym), aby zawsze używać adnotacji. Zdaję sobie sprawę, że powoduje to zamieszanie. Teraz powinno być wyraźniej. Masz rację co do ukrytej części; Nie sądzę, żeby to była wielka sprawa osobiście. – polygenelubricants

+1

użycie metody "T" zamiast "E" dla metody byłoby lepsze, ale cały "projekt" nadal wydaje się błędny. – Bozho