Korzystając z programowania obiektowego mamy moc tworzenia klasy wewnątrz klasy (klasa zagnieżdżona), ale nigdy nie tworzyłem zagnieżdżonej klasy w ciągu 4 lat doświadczenia w programowaniu.
Do czego służą klasy zagnieżdżone?
Wiem, że klasa może być oznaczona jako prywatna, jeśli jest zagnieżdżona i że możemy uzyskać dostęp do wszystkich prywatnych członków tej klasy z klasy zawierającej. Możemy po prostu umieścić zmienne jako prywatne w samej klasie zawierającej.
Po co więc tworzyć klasę zagnieżdżoną?
W jakich scenariuszach należy zastosować klasy zagnieżdżone, czy są one bardziej wydajne pod względem wykorzystania niż inne techniki?
c#
object-oriented
programming-practices
.net
class-design
mayur rathi
źródło
źródło
Odpowiedzi:
Główną cechą zagnieżdżonych klas jest to, że mogą uzyskiwać dostęp do prywatnych członków klasy zewnętrznej, mając jednocześnie pełną moc samej klasy. Mogą być również prywatne, co pozwala na pewne dość potężne enkapsulacje w pewnych okolicznościach:
Tutaj zamykamy całkowicie seter do fabryki, ponieważ klasa jest prywatna, żaden konsument nie może go spuścić i uzyskać dostępu do setera, a my możemy całkowicie kontrolować, co jest dozwolone.
Poza tym jest przydatny do wdrażania interfejsów stron trzecich w kontrolowanym środowisku, w którym nadal możemy uzyskać dostęp do członków prywatnych.
Jeśli na przykład zapewnilibyśmy wystąpienie jakiegoś interfejsu do jakiegoś innego obiektu, ale nie chcemy, aby nasza klasa główna go implementowała, moglibyśmy pozwolić, aby klasa wewnętrzna go zaimplementowała.
źródło
Outer
, przekazałbyśFunc<int>
, który byłby po prostu() => _example
Inner
zagnieżdżonych iinternal
nie działa (tj. Gdy nie masz do czynienia z różnymi zestawami). Uderzenie czytelności z klas zagnieżdżania sprawia, że jest mniej korzystne niż używanieinternal
(w miarę możliwości).Zazwyczaj zagnieżdżona klasa N jest tworzona wewnątrz klasy C, ilekroć C musi użyć czegoś wewnętrznego, co nigdy nie powinno (bezpośrednio) być używane poza C, i z jakiegokolwiek powodu, że coś musi być nowym typem obiektu, a nie jakimś istniejącym rodzaj.
Wierzę, że najczęściej zdarza się to przy implementacji metody, która zwraca obiekt implementujący jakiś interfejs, i chcemy ukryć konkretny typ tego obiektu, ponieważ nie będzie on przydatny nigdzie indziej.
Implementacja IEnumerable jest dobrym przykładem tego:
Po prostu nie ma powodu, aby ktokolwiek poza nim
BlobOfBusinessData
wiedział lub troszczył się o konkretnyBusinessDatumEnumerator
typ, więc równie dobrze możemy go zatrzymać w środkuBlobOfBusinessData
.To nie miał być przykład „najlepszych praktyk”, jak
IEnumerable
prawidłowo wdrożyć , tylko absolutne minimum, aby zrealizować ten pomysł, więc pominąłem takie rzeczy, jak wyraźnaIEnumerable.GetEnumerator()
metoda.źródło
Node
klasa wLinkedList
. Każdy, kto korzysta zLinkedList
pliku, nie dba o sposób jegoNode
implementacji, o ile ma dostęp do zawartości. Jedyną istotą, która w ogóle się przejmuje, jestLinkedList
sama klasa.Mogę wymyślić kilka ważnych powodów:
1. Włącz enkapsulację
Wielokrotnie zagnieżdżone klasy są szczegółami implementacji klasy. Użytkownicy głównej klasy nie powinni martwić się o swoje istnienie. Powinieneś być w stanie je zmieniać do woli, bez konieczności zmiany kodu przez użytkowników klasy głównej.
2. Unikaj zanieczyszczenia nazwy
Nie należy dodawać typów, zmiennych, funkcji itp. W zakresie, chyba że są one odpowiednie w tym zakresie. Jest to nieco inne niż kapsułkowanie. Przydatne może być ujawnienie interfejsu typu zagnieżdżonego, ale właściwym miejscem dla typu zagnieżdżonego jest nadal główna klasa. W środowisku C ++ typy iteratorów są jednym z takich przykładów. Nie mam wystarczającego doświadczenia w języku C #, aby podać konkretne przykłady.
Stwórzmy uproszczony przykład, aby zilustrować, dlaczego przenoszenie zagnieżdżonej klasy do tego samego zakresu co główna klasa jest zanieczyszczeniem nazw. Załóżmy, że implementujesz klasę połączonych list. Normalnie byś użył
Jeśli zdecydujesz się przejść
Node
do tego samego zakresu coLinkedList
, będziesz miećLinkedListNode
jest mało prawdopodobne, aby był użyteczny bezLinkedList
samej klasy. Nawet jeśliLinkedList
udostępniono pewne funkcje, które zwracająLinkedListNode
obiekt, zLinkedList
którego użytkownik może korzystać, nadal jestLinkedListNode
użyteczny tylko wtedy, gdyLinkedList
jest używany. Z tego powodu uczynienie klasy „węzła” klasą równorzędnąLinkedList
zanieczyszcza zawarty zakres.źródło
Używam publicznych klas zagnieżdżonych do powiązanych klas pomocniczych.
Użyj ich do powiązanych odmian.
Dzwoniący może wybrać wersję odpowiednią dla danego problemu. Czasami klasy nie można w pełni skonstruować w jednym przebiegu i wymaga ona wersji modyfikowalnej. Jest to zawsze prawdziwe w przypadku obsługi danych cyklicznych. Zmienne można później przekształcić w tylko do odczytu.
Używam ich do wewnętrznych zapisów
źródło
Zagnieżdżonej klasy można użyć, gdy chcesz utworzyć więcej niż jedną instancję klasy lub gdy chcesz, aby ten typ był bardziej dostępny.
Klasa zagnieżdżona zwiększa enkapsulacje, a także prowadzi do bardziej czytelnego i łatwiejszego do utrzymania kodu.
źródło