Podczas jednego z moich badań nad zawiłościami języka C # natknąłem się na interesujący fragment dotyczący jawnego wdrożenia interfejsu.
While this syntax is quite helpful when you need to resolve name clashes,
you can use explicit interface implementation simply to hide more "advanced"
members from the object level.
Różnica między zezwalaniem na użycie object.method()
lub wymaganiem rzutu ((Interface)object).method()
wydaje mi się niedorzecznym zaciemnieniem dla moich niedoświadczonych oczu. Tekst zauważyć, że ukryje metodę z IntelliSense na poziomie obiektu, ale dlaczego ty chcesz zrobić, że jeśli to nie było konieczne, aby uniknąć konfliktów nazw?
c#
design
interfaces
Natanus
źródło
źródło
Odpowiedzi:
Wyobraź sobie sytuację, w której interfejs zmusza klasę do implementacji metod, które w rzeczywistości nie mają sensu jako części klasy. Może się to często zdarzyć, gdy interfejsy są szczególnie duże i naruszają zasadę segregacji interfejsów.
Ta klasa musi implementować interfejs, ale zamiast zanieczyszczać jego dobrze widoczny interfejs publiczny metodami, które nie mają sensu, można jawnie zaimplementować te metody, które nie powinny być oczywiście dostępne. Wysoce widoczny interfejs publiczny klasy określa sposób, w jaki klasa ma być używana, a jawna implementacja ma miejsce, gdy dostęp do klasy uzyskuje się przez interfejs.
źródło
IEnumerable<T>
która zachowuje się jak połączenie dwóch innych. JeśliIEnumerable<T>
zawiera właściwość określającą, czy jej liczba była znana, potencjalnie nieskończona, czy też żadna, wraz z metodą zapytania o jej liczbę, klasa, która agreguje wielokrotnośćIEnumerable<T>
i zachowuje się jak konkatenacja, mogłaby skutecznie zgłosić liczbę w przypadku, gdy niektóre kapsułkowane kolekcje znały ich liczbę.Najbardziej użyteczną aplikacją, którą znalazłem, jest wdrażanie fabryk. W wielu przypadkach przydatne jest tworzenie klas, które można modyfikować w fabryce, ale niezmienne dla klas zewnętrznych. Można to łatwo wdrożyć w Javie za pomocą klas wewnętrznych, ustawiając pola i ich ustawiacze jako prywatne i ujawniając gettery jako członków publicznych. Jednak w C # musiałem użyć jawnych interfejsów, aby osiągnąć to samo. Wyjaśnię dalej:
W Javie klasa wewnętrzna ORAZ klasa zewnętrzna mogą uzyskiwać dostęp do prywatnych członków siebie, co ma całkowity sens, ponieważ klasy są ze sobą ściśle powiązane. Są w tym samym pliku kodu i prawdopodobnie zostały opracowane przez tego samego programistę. Oznacza to, że fabryki mogą nadal uzyskiwać dostęp do prywatnych pól i metod w klasie wewnętrznej w celu modyfikacji ich wartości. Ale klasy zewnętrzne nie będą miały dostępu do tych pól, chyba że za pośrednictwem ich publicznych modułów pobierających.
Jednak w języku C # klasy zewnętrzne nie mogą uzyskać dostępu do prywatnych członków klas wewnętrznych, więc koncepcja nie ma bezpośredniego zastosowania. Użyłem jawnego interfejsu jako obejścia, definiując prywatny interfejs w klasie zewnętrznej i jawnie implementując go w klasie wewnętrznej. W ten sposób tylko klasa zewnętrzna może uzyskać dostęp do metod w tym interfejsie w taki sam sposób jak w Javie (ale muszą to być metody, a nie pola).
Przykład:
Do tego użyłbym jawnych interfejsów.
źródło
Jeśli klasa implementuje dwa interfejsy zawierające element członkowski z tym samym podpisem, wówczas implementacja tego elementu w klasie spowoduje, że oba interfejsy będą używać tego elementu jako swojej implementacji. W poniższym przykładzie wszystkie wywołania w celu
Paint
wywołania tej samej metody. DO#Natomiast wyraźna implementacja jednego (lub obu) z nich pozwala określić różne zachowania dla każdego z nich.
źródło
Jawne interfejsy są przydatne, gdy albo obiekt ma dwie lub więcej bardzo wyraźnych form komunikacji.
Na przykład obiekt, który utrzymuje kolekcję obiektów potomnych, które muszą komunikować się z rodzicem.
Są pewne akcje, które chcemy, aby były dostępne tylko dla zewnętrznych rozmówców, a niektóre akcje, które chcemy, aby były dostępne tylko dla obiektów potomnych.
Jawne interfejsy pomagają zapewnić ten podział.
źródło
Być może, jeśli masz funkcjonalność, która była przydatna dla użytkowników, ale tylko wtedy, gdy naprawdę wiesz, co robisz (wystarczy przeczytać dokumentację, aby dowiedzieć się o tej funkcji), ale może to popsuć, jeśli tego nie zrobisz.
Dlaczego miałbyś to zrobić zamiast oferować, powiedzmy drugi „interfejs zaawansowanych funkcji”, nie wiem.
źródło
Kod jest na ogół czytany więcej niż jest napisany i używam Intellisense tylko do szybkiego pisania kodu. Nie pisałbym kodu w szczególny sposób, aby Intellisense był ładniejszy.
Nie bardzo rozumiem jak
Obiekt ((Interfejs)) .method () jest bardziej czytelny niż obiekt.method ().
Gdybym miał wiele metod na danym obiekcie, mógłbym zapytać, czy jest to obiekt boga i czy rzeczywiście powinien zostać podzielony na wiele prostszych obiektów.
źródło