2013-05-20 19 views
5

Próbuję zrozumieć ogólne metody w Javie. Biorąc pod uwagę następujący kod:Zrozumienie ogólnych metod java

public class GenericTest { 

    interface Shape { 
     public long area(); 
    } 

    public static class Triangle implements Shape 
    { 
     private long base, height; 
     public long area() { return (base * height)/2; } 
    } 

    public static class Rectangle implements Shape 
    { 
     private long width, height; 
     public long area() { return width * height; } 
    } 

    public <T extends Shape> long area1(T shape) 
    { 
     return shape.area(); 
    } 

    public long area2(Shape shape) 
    { 
     return shape.area(); 
    } 

} 

nie widzi/nie rozumie, dlaczego powinno się używać/wdrożyć AREA1 zamiast obszarze2 (lub odwrotnie). Czy czegoś brakuje? Czy obie metody nie robią tego samego?

ona zostawiła mnie nieco mylić dotyczące rodzajowych w Javie

+1

Nie ma sensu używać generycznych w tym przypadku. Przypadki, w których to * działa * mają sens, gdy nie wiesz, jakiego rodzaju typy musisz ** przechowywać **. –

+1

W tym przypadku, ponieważ @LukasKnuth powiedział, że nie musisz tworzyć ogólnej wersji obszaru powierzchni2() jest dopuszczalne; Jednak obecna dokumentacja oracle pokazuje świetne przykłady na temat generycznych. Przykłady generycznych symboli wieloznacznych mogą również pomóc w wyjaśnieniu zamieszania. Zajrzyj na http://docs.oracle.com/javase/tutorial/extra/generics/methods.html –

+0

Patrzyłem na generics jako przybliżony odpowiednik C++ szablony. Kluczową rzeczą, którą wskazałeś tutaj, jest brak innych odpowiedzi (i całkiem możliwe, że brakuje mi pojęcia, że ​​są używane "kiedy nie wiesz, jaki typ ** przechowywać **." Który jest dokładnie czego szukałem w odpowiedzi :-) – Xaq

Odpowiedz

4

Nie ma dobry powód do tworzenia metodę area1. Preferowana jest metoda area2. Generics mają być stosowane, gdy istnieje związek z konkretnym, ale nieznanym typem. Tutaj nie ma nic szczególnego w parametrze shape. Interfejs Shape pozwala nam już używać metody area, więc nie obchodzi nas, która konkretna implementacja Shape jest przekazywana jako shape. Więc generics nie są tutaj potrzebne.

Zastosowanie

public long area2(Shape shape) 
13

W przykładzie, ponieważ parametr T typu nie są wykorzystywane w żadnej wartości zwracanych, nie ma różnicy.

jednak wyobrazić miał następujące metody:

public <T extends Shape> T movedShape1(T shape) { 
    return shape.move(); 
} 

public Shape movedShape2(Shape shape) { 
    return shape.move(); 
} 

Tutaj widać wyraźną przewagę do korzystania movedShape1(). Otrzymasz bardziej szczegółowy typ dla wartości zwrotnej, nie tracąc żadnego rodzaju bezpieczeństwa.

+0

Czy to nie jest wciąż to samo? Nie widzę dodatkowego bezpieczeństwa typu, obaj zwracają Kształt, prawda? – Xaq

+2

@Xaq: Jeśli posiadasz klasę 'Circle implementuje Shape', to wywołanie' movedShape1() 'z parametrem' Circle' zwróci 'Circle', a nie' Shape'. Wywołanie 'movedShape2()' z tym samym parametrem 'Circle' dałoby" Kształt ". – Keppil

+0

@Xaq, Keppil ma rację, i jest to bardzo przydatne, gdy wywołuje się taką metodę. – dantuch

0

W tej sprawie - Kształt nie jest klasą (abstrakcyjną), ale interfejsem, więc musi zostać zaimplementowany (rozszerzony w formie grenicznej) - powiedziałbym, że robią to samo, i dodawanie generycznych tam jest tylko śledzenie tego, co naprawdę się dzieje

Powiązane problemy