2016-10-05 15 views
8

Próbowałem skondensować ten problem do najmniejszej możliwej ilości kodu.Problem z parametrami typu Java dla zwracanych wartości

Mam zdefiniowaną strukturę tabeli, podobnie jak tabelę bazy danych, z klasami i Table poniżej. A Table jest zasadniczo listą . Chcę, aby podklasy określały ich szczególny aromat Table i i chcę, aby kompilator przechwytywał niewłaściwe próby umieszczenia wierszy jednego typu w tabelach niekompatybilnego typu.

Klasa abstrakcyjna Agent zapewnia metodę pobierania parametrów i zwracania tabeli, która pobiera wiersze typu T. Zdefiniowałem trzy metody ilustrujące problem, który mam.

W FinalAgent, FinalTable i FinalRow zajęcia określić implementacje Agent, Table i klas. Ostatecznie, czego chcę, to method2a, który pobiera listę parametrów i zwraca tabelę typu FinalTable.

public abstract class Row {} 
public abstract class Table<T extends Row> {} 
public abstract class Agent { 
    public <T extends Row> Table<T> method1(List<String> parameter) { 
     return null; 
    } 
    public <T extends Row> Table<T> method2a(List<String> parameter) { 
     return null; 
    } 
    public <T extends Row> Table<T> method2b(String parameter) { 
     return null; 
    } 
} 

public class FinalRow extends Row {} 
public class FinalTable extends Table<FinalRow> {} 
public class FinalAgent extends Agent { 
    @Override 
    public <T extends Row> Table<T> method1(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2a(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2b(String parameter) { 
     return null; 
    } 
} 

Na dole:

  • method1 z FinalAgent kompilacji, ale muszę napisać Table<FinalRow> t1 = new FinalAgent().method1(null); w celu wywołania metody.
  • method2a z FinalAgent Zmieniłem typ zwracany do FinalTable odzwierciedlać to, co ja rzeczywiście powrocie (Chcę napisać FinalTable t2a = new FinalAgent().method2a(null);), ale kompilator generuje błąd: Metoda method2a (Lista) typu FinalAgent musi zastąpić lub zaimplementować metoda supertype
  • method3 Zmieniłem parametr z List na String. Metoda kompiluje OK, ale daje mi ostrzeżenie o typie bezpieczeństwa, z którym mogę przynajmniej pracować.

Więc wreszcie pytanie: czy jest to błąd kompilatora, który method2a w FinalAgent nie ma jeszcze method2b skompilować skompilować?

Równie dobrze mogę zapytać, czy istnieje lepszy sposób na robienie tego, co robię?

+0

@ElliottFrisch gdzie jest surowy typ? – shmosel

+0

@ shmosel Mój błąd, przegapiłem typ ogólny w deklaracji 'FinalTable'. –

+0

To jest osobliwa rozbieżność. – shmosel

Odpowiedz

8

Nie jest jasne, dlaczego parametryzujesz metody. Obiecujesz, że zwrócisz Table<T>, ale Twoja metoda nie może zidentyfikować T w środowisku wykonawczym z powodu usunięcia typu. Prawdopodobnie chcesz parametryzacji całą Agent klasę zamiast:

public abstract class Agent<T extends Table<?>> { 
    public T method1(List<String> parameter) { 
     return null; 
    } 
    public T method2a(List<String> parameter) { 
     return null; 
    } 
    public T method2b(String parameter) { 
     return null; 
    } 
} 

public class FinalAgent extends Agent<FinalTable> { 
    @Override 
    public FinalTable method1(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2a(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2b(String parameter) { 
     return null; 
    } 
} 

Co do początkowego pytania, nie mogę zrozumieć rozbieżności lub komunikatu ostrzegawczego na method2b.

1

Użycie parametru sposobie w jednym miejscu oznacza, że ​​parametr jest zazwyczaj zbędne

ze sposobami, jak przedstawione na Agent, FinalAgent kompiluje:

public Table<? extends Row> method2a(List<String> parameter) { 
    return null; 
} 
public Table<? extends Row> method2b(String parameter) { 
    return null; 
} 
1

Jest to bezpośrednia konsekwencja surowego typu.

  • method1 jest nadal metodą rodzajową: bez problemu.
  • method2b już nie jest to metoda rodzajowa jednak przesłonić metodę w Agent: no problem (z wyjątkiem ostrzeżenia bezpieczeństwa, choć ze względu na niesprawdzony konwersji)
  • method2a już nie jest to metoda rodzajowa ale nie zastąpi nic

method2a widać zadeklarował tak od FinalAgent po kompilacji:

public Table method2a(List parameter) 

Ale jak to określono w FinalAgent:

public FinalTable method2a(List<String> parameter) 

A teraz jesteś zatrzymany. Samo usuwanie ale nie zastąpi prawidłowo method2a

Oto prosty przykład:

public interface Foo 
{ 
    public void bar(List a); 
} 

public class FooChild implements Foo 
{ 
    @Override 
    public void bar(List<String> a) 
    { 
    } 
} 

Daje The method bar(List<String>) of type FooChild must override or implement a supertype method

public interface Foo 
{ 
    public void bar(List a); 
} 

public class FooChild implements Foo 
{ 
    public void bar(List<String> a) 
    { 
    } 
} 

Daje Name clash: The method bar(List<String>) of type FooChild has the same erasure as bar(List) of type Foo but does not override it

Innym przykładem. Ten kod kompiluje grzywny:

public interface Foo 
{ 
    public void bar(List<String> a); 
} 

public class FooChild implements Foo 
{ 
    public void bar(List<String> a) 
    { 
    } 
} 

tego nie robi:

public interface Foo 
{ 
    public <T> void bar(List<String> a); 
} 

public class FooChild implements Foo 
{ 
    public void bar(List<String> a) 
    { 
    } 
} 

Daje Name clash: The method bar(List<String>) of type FooChild has the same erasure as bar(List<String>) of type Foo but does not override it

Jak tylko bar staje się metoda rodzajowa, to widać z surowych rodzajów i możemy zauważyć, ten sam problem.

Innym przykładem surowego typu emisji: Name clash when overriding method of generic class

+0

Gdzie jest surowiec? Dlaczego istnieje niesprawdzona konwersja? – shmosel

+0

'method2a' jest widziane z surowym typem w' Agent', ponieważ jest to rodzajowa metoda z typowym typem T – ToYonos

+0

Niezaznaczona konwersja pochodzi z 'FinalTable'. Kompilator nie może potwierdzić, że jest to ' Table ' in 'method2b' – ToYonos

Powiązane problemy