2013-05-22 14 views
7

To jest moje pierwsze pytanie, mam nadzieję, że jest wystarczająco użyteczne, zarówno dla czytelników, jak i dla mnie! Przez ostatnie dwa dni szukałem go w Google przez cały ten czas.Oddanie ogólnej klasy nadrzędnej do podklasy

mam abstrakcyjny model i pamięci masowej klasy, z którego beton klasy modelu i magazynowania są pochodne:

abstract class Food {} 

abstract class FoodStorage<T extends Food> { 
    abstract void setFood(T food); 
} 

class Apple extends Food {} 

class Basket extends FoodStorage<Apple> { 
    @Override 
    void setFood(Apple apple) { 
     // Save that apple to the basket 
    } 
} 

żaden problem. Teraz chciałbym móc zadzwonić pod numer save() bezpośrednio na instancję Apple, zachowując ją do jej Basket (bez konieczności zawracania sobie głowy koszem) i zaimplementować ją w klasach abstrakcyjnych. Najlepszym Mam jeszcze znaleźć to:

abstract class Food<T extends Food<T,S>, 
     S extends FoodStorage<T,S>> { 

    abstract S getStorage(); 

    void save() { 
     getStorage().setFood((T)this); // <---- Unchecked cast warning 
    } 

} 

abstract class FoodStorage<T extends Food<T,S>, S extends FoodStorage<T,S>> { 
    abstract void setFood(T food); 
} 

class Apple extends Food<Apple,Basket> { 
    Basket basket = new Basket(); // or Basket.getInstance(); 

    @Override 
    Basket getStorage() { 
     return basket; 
    } 
} 

class Basket extends FoodStorage<Apple,Basket> { 
    @Override 
    void setFood(Apple apple) { 
     // Save that apple to the basket 
    } 
} 

który pracuje, ale IntelliJ daje mi ostrzeżenie o niesprawdzony oddanych w save(). Rzeczywiście, przesyłam od Food<T,S> do T.

Pytanie: w jaki sposób mogę zaimplementować ten apple.save() w sposób bezpieczny?

Nie chcę żadnych symboli zastępczych pojawiających się w kodzie klienta, więc zmiana abstract void setFood(T food); na abstract <Z extends Food<T,S>> void setFood(Z food); nie jest rozwiązaniem. (Oczywiście unikam też SupressWarnings("unchecked")).

Jestem świadomy Java Generics, how to avoid unchecked assignment warning when using class hierarchy?, Generics cast issue i The get-put principle, ale nadal nie mogę się z tym pogodzić.

Z góry dziękuję!

+1

co próbujesz zrobić to odlewania klasa nadrzędna obj to klasie potomnej obj, teraz powinno to być niezaznaczone ostrzeżenie, ale musisz przekazać argument, który rozszerza Food i rzuca go na klasę potomną, jak Apple lub Banana ... Gdybym był tobą, zrobiłbym to void save() { getStorage(). setFood (this);} 'i nadpisanie tej metody w każdej klasie rozszerza jedzenie. tak więcej kodu, ale bardziej solidnego projektu:/ –

+1

Powiązane: [Czy istnieje sposób, aby odnieść się do bieżącego typu ze zmienną typu?] (http://stackoverflow.com/questions/7354740/is-there-a-way- to-refer-to-the-current-type-with-a-type-variable) –

+0

(Dzięki za edycję Andersa) – wehlutyk

Odpowiedz

6

Wydaje mi się, że projekt jest raczej wątpliwy, aby mieć wzajemną zależność między żywnością a jej przechowywaniem. Jednokierunkowy depedency byłoby uproszczenie rodzajowych kolosalne:

class Food { ... } 
class FoodStorage<F extends Food> { 
    void setFood(F f); 
} 

Ale jeśli nalegać na wzajemnej zależności, można to zrobić bez obsady następująco:

abstract class Food<F extends Food<F, S>, S extends FoodStorage<F, S>> { 
    abstract F getThis(); 
    abstract S getStorage(); 

    void save() { 
     getStorage().setFood(getThis()); 
    } 
} 
abstract class FoodStorage<F extends Food<F, S>, S extends FoodStorage<F, S>> { 
    abstract void setFood(F food); 
} 
+0

Genialny! Chodzi mi o coś takiego, ale "to" jest genialne –

+0

meh! Powiedziałbym to samo;) –

+0

Miło, i dziękuję @Muhammad. O wzajemnej zależności, do której nie jestem szczególnie przywiązany, po prostu nie widzę innego sposobu implementacji 'apple.save()'. Jeśli sugestia pojawi się przed kilkoma dniami bez wzajemnej zależności, wezmę to jako odpowiedź, a drugą poprawię tę odpowiedź jako ostateczną. – wehlutyk

Powiązane problemy