To nie jest oszustwo, ale jak każde narzędzie, powinno być używane do tego, co ma rozwiązać. Refleksja z definicji pozwala ci sprawdzać i modyfikować kod poprzez kod; jeśli to właśnie musisz zrobić, to odbicie jest narzędziem do pracy. Refleksja dotyczy przede wszystkim meta-kodu: kodu, który celuje w kod (w przeciwieństwie do zwykłego kodu, który celuje w dane).
Przykładem dobrego zastosowania refleksji są ogólne klasy interfejsu usługi sieciowej: Typowym rozwiązaniem jest oddzielenie implementacji protokołu od funkcjonalności ładunku. Mamy więc jedną klasę (nazwijmy ją T
), która implementuje ładunek, a drugą, która implementuje protokół ( P
). T
jest dość proste: dla każdego połączenia, które chcesz wykonać, po prostu napisz jedną metodę, która zrobi wszystko, co powinna. P
musi jednak mapować wywołania usługi internetowej na wywołania metod. Uczynienie tego mapowania ogólnym jest pożądane, ponieważ pozwala uniknąć nadmiarowości i sprawia, że można go P
wielokrotnie używać. Refleksja zapewnia środki do sprawdzania klasy T
w czasie wykonywania i wywoływania jej metod na podstawie ciągów przekazywanych P
przez protokół usługi sieci Web, bez wiedzy klasy na temat kompilacjiT
. Stosując zasadę „kod o kodzie” można argumentować, że klasa P
ma kod w klasie T
jako część swoich danych.
Jednak.
Refleksja daje również narzędzia do obejścia ograniczeń systemu typów językowych - teoretycznie można przekazać wszystkie parametry jako typ object
i wywołać ich metody poprzez refleksje. Voilà, język, który ma wymuszać silną dyscyplinę pisania statycznego, zachowuje się teraz jak język dynamicznie pisany z późnym wiązaniem, tyle że składnia jest znacznie bardziej rozbudowana. Każde wystąpienie takiego wzoru, które do tej pory widziałem, było brudnym włamaniem i niezmiennie możliwe byłoby rozwiązanie w systemie typów językowych, które byłoby bezpieczniejsze, bardziej eleganckie i wydajniejsze pod każdym względem .
Istnieje kilka wyjątków, takich jak kontrolki GUI, które mogą być powiązane z różnymi niepowiązanymi typami źródeł danych; nakazanie, aby Twoje dane implementowały określony interfejs tylko po to, abyś mógł go powiązać, nie jest realistyczne, a programista nie implementuje adaptera dla każdego typu źródła danych. W takim przypadku bardziej przydatne jest zastosowanie odbicia w celu wykrycia rodzaju źródła danych i dostosowanie powiązania danych.