Nie rozumiem, dlaczego w adnotacjach Java nie ma dziedziczenia, podobnie jak w klasach Java. Myślę, że byłoby to bardzo przydatne.
Na przykład: Chcę wiedzieć, czy dana adnotacja jest walidatorem. Dzięki dziedziczeniu mogłem odruchowo poruszać się po superklasach, aby wiedzieć, czy ta adnotacja rozszerza ValidatorAnnotation
. W przeciwnym razie, jak mogę to osiągnąć?
Czy ktoś może podać mi powód tej decyzji projektowej?
java
inheritance
annotations
sinuhepop
źródło
źródło
java.lang.annotation.Annotation
, tzn. Każda adnotacjainstanceof
, chociaż fakt ten nie jest wyraźnie zadeklarowany.Odpowiedzi:
O tym, dlaczego nie został zaprojektowany w ten sposób, można znaleźć odpowiedź w często zadawanych pytaniach dotyczących projektu JSR 175 , gdzie jest napisane:
Tak, tak myślę, powodem jest po prostu KISS. W każdym razie wydaje się, że ten problem (wraz z wieloma innymi) jest rozpatrywany jako część JSR 308 , a można nawet znaleźć alternatywny kompilator z tą funkcjonalnością, którą opracował już Mathias Ricken .
źródło
Rozszerzalne adnotacje skutecznie zwiększyłyby ciężar określania i utrzymywania innego systemu typów. Byłby to dość unikalny system typów, więc nie można po prostu zastosować paradygmatu typu OO.
Zastanów się nad wszystkimi problemami, gdy wprowadzasz polimorfizm i dziedziczenie adnotacji (np. Co się stanie, gdy subnotacja zmieni specyfikacje meta-adnotacji, takie jak retencja?)
A wszystko to dodatkowo komplikuje przypadek użycia?
Chcesz wiedzieć, czy dana adnotacja należy do kategorii?
Spróbuj tego:
Jak widać, można łatwo grupować i kategoryzować adnotacje bez zbędnego bólu, korzystając z udostępnionych udogodnień.
Tak więc KISS jest powodem, dla którego nie wprowadzono systemu typu meta-typ do języka Java.
[edycja ps]
Użyłem ciągu tylko do demonstracji i ze względu na otwartą meta adnotację. W przypadku własnego projektu możesz oczywiście użyć wyliczenia typów kategorii i podać wiele kategorii („wielokrotne dziedziczenie”) dla danej adnotacji. Pamiętaj, że wartości są całkowicie fałszywe i służą wyłącznie do celów demonstracyjnych:
źródło
@Target(ElementType.ANNOTATION_TYPE) @Retention(RetentionPolicy.RUNTIME) @interface C {}; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @C public @interface F {} class a{ @F public void S() {} } @Test public void blahTest() throws NoSuchMethodException { Method m = a.class.getMethod("S"); System.out.println(m.isAnnotationPresent(C.class)); }
W pewnym sensie masz to już z Adnotacjami - meta Adnotacjami. Jeśli adnotacja ma adnotację z meta informacją, jest to na wiele sposobów równoważne rozszerzeniu dodatkowego interfejsu. Adnotacje są interfejsami, więc polimorfizm tak naprawdę nie wchodzi w grę, a ponieważ mają charakter statyczny, nie można wywoływać dynamicznej emisji.
W swoim przykładzie walidatora możesz po prostu dodać adnotację i zobaczyć, czy ma ona meta-adnotację walidatora.
Jedynym przypadkiem, w którym mogłem zobaczyć, że dziedziczenie pomogłoby, jest to, że chcesz mieć adnotację według supertypu, ale to dodałoby całą złożoność, ponieważ dana metoda lub typ może mieć na sobie dwie takie adnotacje, co oznacza, że tablica musiałaby zostać zwrócona zamiast tylko jednego obiektu.
Myślę więc, że ostateczną odpowiedzią jest to, że przypadki użycia są ezoteryczne i komplikują bardziej standardowe przypadki użycia, co sprawia, że nie warto.
źródło
Projektanci obsługi adnotacji Java wprowadzili szereg „uproszczeń” ze szkodą dla społeczności Java.
Brak podtypów adnotacji powoduje, że wiele złożonych adnotacji jest niepotrzebnie brzydkich. W adnotacjach nie można po prostu mieć atrybutu, który może zawierać jedną z trzech rzeczy. Trzeba mieć trzy oddzielne atrybuty, które dezorientują programistów i wymagają sprawdzania poprawności w czasie wykonywania, aby upewnić się, że używany jest tylko jeden z trzech.
Tylko jedna adnotacja danego typu na witrynę. Doprowadziło to do zupełnie niepotrzebnego wzorca adnotacji kolekcji. @Validation i @Validations, @Image i @Images itp.
Drugi jest naprawiany w Javie 8, ale jest już za późno. Wiele frameworków zostało napisanych w oparciu o to, co było możliwe w Javie 5, a teraz te brodawki API pozostaną na długo.
źródło
Być może spóźniłem się o trzy lata, odpowiadając na to pytanie, ale uznałem to za interesujące, ponieważ znalazłem się w tym samym miejscu. Oto moje zdanie na ten temat. Adnotacje można wyświetlać jako wyliczenia. Zapewniają one jednokierunkową informację - wykorzystaj ją lub zgub.
Miałem sytuację, w której chciałem symulować GET, POST, PUT i DELETE w aplikacji internetowej. Tak bardzo chciałem mieć „super” adnotację o nazwie „HTTP_METHOD”. Później dotarło do mnie, że to nie ma znaczenia. Cóż, musiałem zadowolić się użyciem ukrytego pola w formularzu HTML do identyfikacji DELETE i PUT (ponieważ POST i GET i tak były dostępne).
Po stronie serwera szukałem parametru ukrytego żądania o nazwie „_method”. Jeśli wartością było PUT lub DELETE, zastąpiło to powiązaną metodę żądania HTTP. Powiedziawszy to, nie miało znaczenia, czy muszę przedłużyć adnotację, aby wykonać pracę. Wszystkie adnotacje wyglądały tak samo, ale były traktowane inaczej po stronie serwera.
Więc w twoim przypadku upuść swędzenie, aby rozszerzyć adnotacje. Traktuj je jak „markery”. „Reprezentują” niektóre informacje i niekoniecznie „manipulują” niektórymi informacjami.
źródło
Jedną rzeczą, o której mógłbym pomyśleć, jest możliwość posiadania wielu adnotacji. Możesz więc dodać walidator i bardziej szczegółową adnotację w tym samym miejscu. Ale mogę się mylić :)
źródło
Nigdy o tym nie myślałem, ale ... wydaje się, że masz rację, nie ma problemu z funkcją dziedziczenia adnotacji (przynajmniej nie widzę problemu z tym).
O twoim przykładzie z adnotacją „walidator” - możesz wtedy wykorzystać podejście „meta-adnotacja” . Oznacza to, że zastosujesz szczególną meta-adnotację do całego interfejsu adnotacji.
źródło
ten sam problem, który mam. Nie możesz. „Zdyscyplinowałem się”, aby pisać właściwości w adnotacjach, aby przestrzegać niektórych standardów, więc na zewnątrz, kiedy otrzymasz adnotację, możesz „wąchać”, jaki to rodzaj adnotacji według właściwości, które ma.
źródło