Aby wyjaśnić, pytam o to
public class A{
private/*or public*/ B b;
}
vs.
public class A{
private/*or public*/ class B{
....
}
}
Zdecydowanie mogę wymyślić kilka powodów, aby użyć jednego lub drugiego, ale tak naprawdę chciałbym zobaczyć przekonujące przykłady, które pokazują, że zalety i wady są nie tylko akademickie.
object-oriented-design
class-design
EpsilonVector
źródło
źródło
Odpowiedzi:
Są zwykle używane, gdy klasa jest wewnętrznym szczegółem implementacyjnym innej klasy, a nie częścią jej zewnętrznego interfejsu. Widziałem je głównie jako klasy tylko danych, które czyszczą wewnętrzne struktury danych w językach, które nie mają osobnej składni dla struktur typu c. Przydają się także czasami w przypadku wysoce spersonalizowanych obiektów pochodzących z jednej metody, takich jak procedury obsługi zdarzeń lub wątki robocze.
źródło
Załóżmy, że budujesz drzewo, listę, wykres i tak dalej. Dlaczego powinieneś ujawniać wewnętrzne szczegóły węzła lub komórki światu zewnętrznemu?
Każdy, kto korzysta z wykresu lub listy, powinien polegać tylko na jego interfejsie, a nie na implementacji, ponieważ możesz chcieć go zmienić w przyszłości (np. Z implementacji tablicowej na opartą na wskaźnikach), a klienci korzystający z Twojej struktura danych ( każda z nich ) musiałaby zmodyfikować swój kod, aby dostosować go do nowej implementacji.
Zamiast tego hermetyzacja implementacji węzła lub komórki w prywatnej klasie wewnętrznej daje swobodę modyfikowania implementacji w dowolnym momencie, bez konieczności zmuszania klientów do dostosowywania swojego kodu, o ile interfejs Twojej struktury danych pozostaje niezmieniony nietknięty.
Ukrywanie szczegółów implementacji struktury danych prowadzi również do korzyści bezpieczeństwa, ponieważ jeśli chcesz rozpowszechniać swoją klasę, udostępnisz tylko plik interfejsu wraz ze skompilowanym plikiem implementacji i nikt nie będzie wiedział, czy faktycznie używasz tablic lub wskaźników za wdrożenie, chroniąc w ten sposób aplikację przed jakimś wykorzystaniem lub przynajmniej wiedzą z powodu niemożności niewłaściwego użycia lub sprawdzenia kodu. Oprócz kwestii praktycznych nie należy lekceważyć faktu, że w takich przypadkach jest to niezwykle eleganckie rozwiązanie.
źródło
Moim zdaniem uczciwy gliniarz używa klas zdefiniowanych wewnętrznie dla klas, które są krótko używane w klasie, aby umożliwić określone zadanie.
Na przykład, jeśli chcesz powiązać listę danych składającą się z dwóch niepowiązanych klas:
Jeśli twoja klasa wewnętrzna jest używana przez inną klasę, powinieneś ją rozdzielić. Jeśli twoja klasa wewnętrzna zawiera jakąś logikę, powinieneś ją rozdzielić.
Zasadniczo uważam, że świetnie nadają się do zaślepiania otworów w twoich obiektach danych, ale są trudne do utrzymania, jeśli muszą zawierać logikę, ponieważ musisz wiedzieć, gdzie ich szukać, jeśli chcesz to zmienić.
źródło
tuple.ItemX
kod jest niejasny.Klasy wewnętrzne w jakimś języku (na przykład Java) mają powiązanie z obiektem ich zawierającej klasy i mogą używać swoich członków bez ich kwalifikowania. Jeśli są dostępne, jest bardziej przejrzyste niż ich ponowna implementacja przy użyciu innych narzędzi językowych.
Klasy zagnieżdżone w innym języku (na przykład C ++) nie mają takiego powiązania. Po prostu używasz zakresu i kontroli dostępności zapewnianej przez klasę.
źródło
Unikam klas wewnętrznych w Javie, ponieważ wymiana na gorąco nie działa w obecności klas wewnętrznych. Nienawidzę tego, ponieważ naprawdę nie lubię narażać się na kompromis w kodzie dla takich rozważań, ale te ponowne uruchomienie Tomcat sumują się.
źródło
Jednym z zastosowań prywatnej statycznej klasy wewnętrznej jest wzorzec Memo. Wszystkie dane, które należy zapamiętać, umieścisz w prywatnej klasie i zwrócisz je z jakiejś funkcji jako Object. Nikt na zewnątrz nie może (bez refleksji, deserializacji, kontroli pamięci ...) zaglądać do niego / modyfikować go, ale może zwrócić go twojej klasie i może przywrócić jej stan.
źródło
Jednym z powodów korzystania z prywatnej klasy wewnętrznej może być to, że używany interfejs API wymaga dziedziczenia od określonej klasy, ale nie chcesz eksportować wiedzy o tej klasie do użytkowników z zewnętrznej klasy. Na przykład:
W tym przypadku do_my_async_op wymaga przekazania do niego obiektu typu callback. To wywołanie zwrotne ma podpis funkcji publicznej członka, którego używa interfejs API.
Kiedy do_op () jest wywoływana z klasy zewnętrznej, używa instancji prywatnej klasy wewnętrznej, która dziedziczy z wymaganej klasy wywołania zwrotnego zamiast wskaźnika do siebie. Klasa zewnętrzna ma odwołanie do klasy zewnętrznej w prostym celu przetaczania wywołania zwrotnego do prywatnej funkcji członka do_callback klasy zewnętrznej .
Zaletą tego jest to, że masz pewność, że nikt inny nie może wywołać publicznej funkcji członka „fire ()”.
źródło
Według Jona Skeeta w C # w Depth, użycie zagnieżdżonej klasy było jedynym sposobem na wdrożenie w pełni leniwego, bezpiecznego dla wątków singletonu (patrz piąta wersja) (do .NET 4).
źródło
Klasy prywatne i wewnętrzne służą do zwiększania poziomów enkapsulacji i ukrywania szczegółów implementacji.
W C ++, oprócz klasy prywatnej, tę samą koncepcję można osiągnąć, implementując anonimową przestrzeń nazw klasy cpp. Służy to do ukrycia / sprywatyzowania szczegółów implementacji.
Jest to ten sam pomysł, co klasa wewnętrzna lub prywatna, ale na jeszcze większym poziomie enkapsulacji, ponieważ jest całkowicie niewidoczny poza jednostką kompilacji pliku. Nic z tego nie pojawia się w pliku nagłówkowym ani nie jest widoczne na zewnątrz w deklaracji klasy.
źródło