2016-08-10 10 views
14

Powiedzmy mamy kilka interfejsów test/zajęcia tak:Dlaczego ogólna metoda interfejsu może być zaimplementowana jako nieobsługiwana w Javie?

abstract class Plant { 
    public abstract String getName(); 
} 

interface Eatable { } 

class Apple extends Plant implements Eatable { 
    @Override 
    public String getName() { 
     return "Apple"; 
    } 
} 

class Rose extends Plant { 
    @Override 
    public String getName() { 
     return "Rose"; 
    } 
} 

interface Animal { 
    <T extends Plant & Eatable> void eat(T plant); 
} 

Widać Animal.eat to ogólna metoda z ograniczeniami. Teraz mam Human klasę tak:

class Human implements Animal { 
    @Override 
    public void eat(Plant plant) { 
    } 
} 

który kompiluje grzywny. Widać, że Human.eat jest mniej ograniczony niż Animal.eat, ponieważ interfejs Eatable został utracony.

Pytanie 1: Dlaczego kompilator nie skarży się na tę niespójność?

Q2: Jeśli Plant&Eatableumniejsza do Plant jest dopuszczalne dla kompilatora, dlaczego go narzeka na eat(Object plant)?

+2

Z której wersji Java korzystasz. Używanie środowiska Java 1.8 w środowisku Eclipse zapewnia oczekiwany czas kompilacji zgodnie z oczekiwaniami. – Codebender

+0

@Codebender Java8 w Intellij IDEA. –

+2

@Codebender Nie mam problemu z kompilacją tego. https://ideone.com/7xUcZn – flakes

Odpowiedz

12

Lesson: Generics by Gilad Bracha według niego

public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll) 

To jest przykład daje wiele granic dla parametru typu, użyciem składni & T1 T2 ... & TN. Zmienna typu o wielu limitach jest znana jako podtyp wszystkich typów wymienionych w powiązaniu . Gdy używane jest wielokrotne wiązanie, pierwszy typ wymieniony w powiązaniu jest używany jako wymazanie zmiennej typu.

więc przykładem <T extends Plant & Eatable> void eat(T plant); zostaną usunięte do void eat(Plant plant); więc kiedy go nadpisać kompilator nie skarżą

0

Ahmed odpowiedź jest prawo, przy okazji, jeśli chcesz umieścić ograniczenie wdrażania programu interfejs Animal, należy zadeklarować ją jako to:

interface Animal<T extends Plant & Eatable> { 
    void eat(T plant); 
} 

Następnie, jeśli implementuje interfejs Animal bez podania informacji o typie, kompilator przy najmniejszej niespodzianka politykę wywnioskować T jako typ rośliny. Ale jeśli podasz niezbędne informacje o typie, kompilator działa poprawnie.

class Human implements Animal<Rose> // won't compile 
class Human implements Animal<Apple> // compile 
Powiązane problemy