Czy widoczność private
pól / właściwości / atrybutów klasy jest przydatna? W OOP prędzej czy później zamierzasz utworzyć podklasę klasy, w takim przypadku dobrze jest zrozumieć i móc całkowicie zmodyfikować implementację.
Jedną z pierwszych rzeczy, które robię, gdy podklasuję klasę, jest zmiana zestawu private
metod na protected
. Jednak ukrywanie szczegółów przed światem zewnętrznym jest ważne - więc potrzebujemy, protected
a nie tylko public
.
Moje pytanie brzmi: czy wiesz o ważnym przypadku użycia, w którym private
zamiast protected
jest dobrym narzędziem, czy dwie opcje „ protected
& public
” byłyby wystarczające dla języków OOP?
object-oriented
encapsulation
access-modifiers
Adam Libuša
źródło
źródło
Odpowiedzi:
Ponieważ, jak mówisz,
protected
wciąż masz możliwość „całkowicie zmodyfikować implementację”. To naprawdę nie chroni niczego w klasie.Dlaczego zależy nam na „prawdziwej ochronie” rzeczy w klasie? W przeciwnym razie zmiana szczegółów implementacji bez zerwania kodu klienta byłaby niemożliwa . Innymi słowy, ludzie, którzy piszą podklasy, są także „światem zewnętrznym” dla osoby, która napisała oryginalną klasę podstawową.
W praktyce
protected
członkowie są zasadniczo „publicznym interfejsem API dla podklas” klasy i muszą być stabilni i kompatybilni wstecz tak samo jakpublic
członkowie. Gdybyśmy nie mieli możliwości tworzenia prawdziwychprivate
członków, nic w implementacji nigdy nie byłoby bezpieczne do zmiany, ponieważ nie byłbyś w stanie wykluczyć możliwości, że (nie-złośliwy) kod klienta był w jakiś sposób zależny od to.Nawiasem mówiąc, podczas gdy „W OOP wcześniej czy później zamierzasz utworzyć podklasę klasy” jest technicznie prawdą, twój argument wydaje się opierać na znacznie silniejszym założeniu, że „wcześniej czy później utworzysz podklasę każda klasa ”, co prawie na pewno nie jest prawdą.
źródło
private
sens. Perspektywa lib musi być używana częściej, w przeciwnym razie każdy, kto lubi mentalność kodowania „absolutnej kontroli, absolutnej odpowiedzialności”, może ją oznaczyć jako „chroni mnie przed sobą”. Zauważ, że nadal używałemprivate
poprzednio, zawsze czułem dobrą dokumentację, a konwencja nazewnictwa,_foo
która wskazuje, że prawdopodobnie nie powinnaś się z tym bawić, była równoważna, jeśli nie lepsza. Zdolność do deterministycznego powiedzenia „nic się nie złamie” jest uzasadnioną,private
-tylko cechą.To jest źle. Nie każda klasa powinna być podklasowana, a niektóre statyczne języki OOP mają nawet funkcje, aby temu zapobiec, np.
final
(Java i C ++) lubsealed
(C #).Nie, nie jest. Dobrze jest, aby klasa była w stanie jasno zdefiniować swój interfejs publiczny i zachować niezmienniki, nawet jeśli są dziedziczone.
Ogólnie kontrola dostępu dotyczy podziału na przedziały. Chcesz, aby poszczególne części kodu były rozumiane bez konieczności szczegółowego zrozumienia, w jaki sposób współdziała z resztą kodu. Prywatny dostęp na to pozwala. Jeśli wszystko jest co najmniej chronione, musisz zrozumieć, co robi każda podklasa, aby zrozumieć, jak działa klasa podstawowa.
Lub, ujmując to w kategoriach Scott Meyers: na prywatne części klasy wpływa skończona ilość kodu: kod samej klasy.
Na części publiczne potencjalnie wpływa każdy istniejący fragment kodu i każdy fragment kodu, który należy jeszcze napisać, co stanowi nieskończoną ilość kodu.
Na części chronione potencjalnie ma wpływ każda istniejąca podklasa i każda podklasa, która ma jeszcze zostać napisana, co jest również nieskończoną ilością kodu.
Wniosek jest taki, że chroniony daje niewiele więcej niż publiczny, podczas gdy prywatny daje prawdziwą poprawę. Istnienie specyfikatora chronionego dostępu jest wątpliwe, a nie prywatne.
źródło
virtual
, z powodów przedstawionych w tej odpowiedzi.protected
dotyczy metod, a nie członków danych.sealed
duże części biblioteki .net i IIRC, dlaczego chciałby zamknąć resztę. W momencie, gdy pozwolisz spadkobiercom zewnętrznym zacząć dotykać wartości wewnętrznych, musisz dodać ogromną ilość sprawdzeń poprawności / poprawności do każdej metody, ponieważ nie możesz już ufać żadnym niezmiennikom projektu dotyczącym stanu wewnętrznego obiektów.Tak, prywatne pola są absolutnie konieczne. Właśnie w tym tygodniu musiałem napisać niestandardową implementację słownika, w której kontrolowałem zawartość słownika. Gdyby pole słownika miało być chronione lub upublicznione, wówczas kontrole, które tak starannie napisałem, można by łatwo obejść.
Prywatne pola zazwyczaj dotyczą zapewnienia, że dane są zgodne z oczekiwaniami pierwotnego kodera. Uczyń wszystko chronionym / publicznym, a będziesz jeździł autokarem i koniami przez te procedury i walidację.
źródło
private
to tylko sposób na powiedzenie „nie dotykaj ich” i wymuszenie go w ramach umowy kompilatora. W systemach takich jak .NET ma to również istotny wpływ na bezpieczeństwo - możesz dotykać prywatnych użytkowników tylko wtedy, gdy masz pełne zaufanie (w zasadzie równowartość dostępu administratora / roota).Kiedy próbuje rozumować formalnie o poprawności programu Object Oriented to typowy używać modułowego podejścia obejmującego niezmienników obiektów . W tym podejściu
Modułowe wnioskowanie na temat obiektu przebiega w następujący sposób (przynajmniej w pierwszym przybliżeniu)
Wyobraź sobie, że weryfikujemy
object A
użycie powyższego podejścia. A teraz chcą zweryfikowaćmethod g
zobject B
którym wzywamethod f
oobject A
. Rozumowanie modułowe pozwala nam wnioskowaćmethod g
bez konieczności ponownego rozważania implementacjimethod f
. Pod warunkiem, że możemy ustalić niezmiennośćobject A
i warunek wstępnymethod f
w witrynie wywołującejmethod g,
, możemy przyjąć warunek postumethod f
za podsumowanie zachowania wywołania metody. Ponadto dowiemy się również, że po powrocie połączenia niezmiennikA
nadal się utrzymuje.Ta modułowość wnioskowania pozwala nam formalnie myśleć o dużych programach. Możemy uzasadnić każdą z metod z osobna, a następnie zestawić wyniki tego rozumowania z kolei w celu uzasadnienia większych części programu.
Pola prywatne są bardzo przydatne w tym procesie. Aby wiedzieć, że niezmiennik obiektu nadal utrzymuje się między dwoma wywołaniami metody tego obiektu, zwykle polegamy na tym, że obiekt nie jest modyfikowany w okresie pośrednim.
Aby modułowe rozumowanie działało w kontekście, w którym obiekty nie mają pól prywatnych, musielibyśmy mieć sposób, aby upewnić się, że cokolwiek pole zostanie ustawione przez inny obiekt, że niezmiennik zawsze zostanie ponownie ustanowiony (po polu zestaw). Trudno wyobrazić sobie niezmiennik obiektu, który ma zarówno wartość bez względu na wartość pól obiektu, jak i jest użyteczny w uzasadnieniu poprawności programu. Prawdopodobnie musielibyśmy wymyślić jakąś skomplikowaną konwencję dotyczącą dostępu do pola. I prawdopodobnie także tracimy część (w najgorszym nawet całość) naszej zdolności do wnioskowania modułowego.
Pola chronione
Pola chronione przywracają część naszej zdolności rozumowania modułowego. W zależności od języka
protected
może ograniczać możliwość ustawienia pola na wszystkie podklasy lub wszystkie podklasy i klasy tego samego pakietu. Często zdarza się, że nie mamy dostępu do wszystkich podklas, gdy zastanawiamy się nad poprawnością pisanego obiektu. Na przykład możesz pisać komponent lub bibliotekę, która będzie później używana w większym programie (lub kilku większych programach) - z których niektóre mogą nawet nie zostać jeszcze napisane. Zazwyczaj nie wiesz, czy i w jaki sposób można go zaklasyfikować do podklasy.Zazwyczaj jednak do podklasy należy utrzymanie obiektu niezmiennego dla klasy, którą rozszerza. Tak więc w języku, w którym ochrona oznacza tylko „podklasę”, a my jesteśmy zdyscyplinowani, aby zapewnić, że podklasy zawsze zachowują niezmienniki swojej nadklasy, można argumentować, że wybór użycia chronionego zamiast prywatnego traci tylko minimalną modułowość .
Chociaż mówiłem o formalnym uzasadnieniu, często uważa się, że gdy programiści nieformalnie rozumują poprawność swojego kodu, czasami opierają się na podobnych typach argumentów.
źródło
private
zmienne w klasie są lepsze niżprotected
z tego samego powodu, dla któregobreak
instrukcja wewnątrzswitch
bloku jest lepsza niżgoto label
instrukcja; to znaczy, że programiści są podatni na błędy.protected
zmienne nadają się do nieumyślnego nadużycia (błędy programisty), podobnie jakgoto
oświadczenie nadaje się do tworzenia kodu spaghetti.Czy można napisać działający kod bezbłędny przy użyciu
protected
zmiennych klas? Tak oczywiście! Tak jak jest to możliwe, aby napisać działający kod wolny od błędów przy użyciugoto
; ale jak mówi frazes „Tylko dlatego, że możesz, nie znaczy, że powinieneś!”Klasy, a nawet paradygmat OO, istnieją, aby uchronić się przed nieszczęśliwymi, podatnymi na błędy programistami ludzkimi, popełniającymi błędy. Obrona przed ludzkimi błędami jest tak dobra, jak środki obronne wbudowane w klasę. Wykonanie implementacji twojej klasy
protected
jest równoznaczne z wybiciem ogromnej dziury w ścianach fortecy.Klasy podstawowe nie mają absolutnie żadnej wiedzy o klasach pochodnych. Jeśli chodzi o klasę podstawową,
protected
to nie daje ona żadnej dodatkowej ochronypublic
, ponieważ nic nie stoi na przeszkodzie, aby klasa pochodna utworzyłapublic
moduł pobierający / ustawiający, który zachowuje się jak backdoor.Jeśli klasa podstawowa pozwala na nieograniczony dostęp do wewnętrznych szczegółów implementacyjnych, wówczas sama klasa nie może się bronić przed błędami. Klasy podstawowe nie mają absolutnie żadnej wiedzy o swoich klasach pochodnych, a zatem nie mają możliwości obrony przed błędami popełnionymi w tych klasach pochodnych.
Najlepszą rzeczą, jaką może zrobić klasa podstawowa, jest ukrycie jak największej jej implementacji
private
i wprowadzenie wystarczających ograniczeń, aby uchronić się przed przełamywaniem zmian w klasach pochodnych lub czymkolwiek innym poza klasą.Ostatecznie istnieją języki wysokiego poziomu, aby zminimalizować błędy ludzkie. Istnieją również dobre praktyki programowania (takie jak zasady SOLID ) w celu zminimalizowania błędów ludzkich.
Deweloperzy oprogramowania, którzy ignorują dobre praktyki programistyczne, mają znacznie większą szansę na niepowodzenie i są bardziej podatni na tworzenie zepsutych, niemożliwych do utrzymania rozwiązań. Ci, którzy postępują zgodnie z dobrymi praktykami, mają znacznie mniejsze szanse na porażkę i są bardziej skłonni do wypracowania działających, możliwych do utrzymania rozwiązań.
źródło
public
szczegółów implementacji, ponieważ nadaje się do kodu niemożliwego do utrzymania. Kompetentny programista unikałby,goto
ponieważ nadaje się do kodu niemożliwego do utrzymania. Jednak rzeczywisty świat jest taki, że czasami gubisz się w strasznym bałaganie starszego kodu i nie masz wyboru, jak go użyćgoto
, i z tego samego powodu czasami nie masz wyboru, jak tylko użyć publicznych / chronionych szczegółów implementacji.public
właściwości / interfejs, ale nie z kodem, który tylko używagoto
.goto
czy tylko dlatego, że czytasz takie artykuły? Rozumiem, dlaczegogoto
jest złe, ponieważ spędziłem 2 lata pracując nad starożytnym kodem, który go używa; i spędziłem jeszcze więcej czasu pracując w kodzie, w którym „klasom” wyciekają wszędzie szczegóły implementacji,public
afriend
specyfikatory używane są jako szybkie / łatwe / brudne włamania. Nie zgadzam się z argumentem, że „publiczne ujawnianie szczegółów implementacji” nie może powodować bałaganu spaghetti ze sobą na tym samym poziomie dotkliwości,goto
ponieważ absolutnie może.Klasy dziedziczone mają dwie umowy - jedną z właścicielami odwołań do obiektów i klas pochodnych. Członkowie publiczni są związani umową z posiadaczami referencji, a członkowie chronieni są związani umową z klasami pochodnymi.
Tworzenie członków
protected
sprawia, że jest to bardziej uniwersalna klasa podstawowa, ale często ogranicza możliwości zmiany przyszłych wersji tej klasy. Tworzenie członkówprivate
pozwala autorowi klasy na większą wszechstronność w zmienianiu wewnętrznego funkcjonowania klasy, ale ogranicza rodzaje klas, które można z niej pożytecznie wyprowadzić.Na przykład
List<T>
w .NET czyni prywatny magazyn kopii zapasowych; gdyby był chroniony, typy pochodne mogłyby robić użyteczne rzeczy, które w innym przypadku nieList<T>
byłyby możliwe, ale przyszłe wersje musiałyby na zawsze korzystać z niezgrabnego monolitycznego sklepu z podkładami, nawet w przypadku list zawierających miliony przedmiotów. Ustanowienie prywatnego magazynu kopii zapasowych pozwoliłoby przyszłym wersjomList<T>
na korzystanie z bardziej wydajnego magazynu kopii zapasowych bez rozbijania klas pochodnych.źródło
Myślę, że w twoim argumencie jest kluczowe założenie, że kiedy ktoś pisze klasę, nie wie, kto może przedłużyć tę klasę i z jakiego powodu . Biorąc pod uwagę to założenie, twój argument miałby doskonały sens, ponieważ każda zmienna, którą wybierzesz jako prywatną, mogłaby potencjalnie odciąć drogę rozwoju. Odrzuciłbym jednak to założenie.
Jeśli to założenie zostanie odrzucone, należy rozważyć tylko dwa przypadki.
W tym przypadku autor wie, że ktoś rozszerzy klasę i dlaczego, a zatem będzie wiedział dokładnie, co chronić, a co prywatnie. Używają rozróżnienia prywatnego / chronionego, aby komunikować się z pewnym rodzajem interfejsu dla użytkownika tworzącego podklasę.
Ten przypadek powinien być rzadki (można argumentować, że nie jest uzasadniony) i nie jest preferowany po prostu modyfikowanie oryginalnej klasy w oryginalnej bazie kodu. Może to być również objaw złego projektu. W takich przypadkach wolałbym, aby osoba hakująca w tym zachowaniu korzystała z innych hacków, takich jak przyjaciele (C / C ++) i
setAccessible(true)
(Java).Myślę, że można bezpiecznie odrzucić to założenie.
Zasadniczo sprowadza się to do koncepcji kompozycji zamiast dziedziczenia . Dziedziczenie jest często nauczane jako idealny sposób na ograniczenie ponownego użycia kodu, jednak rzadko powinien być pierwszym wyborem do ponownego użycia kodu. Nie mam prostego argumentu powalającego, a jego zrozumienie może być dość trudne i sporne. Jednak w moim doświadczeniu z modelowaniem domen odkryłem, że rzadko korzystam z dziedziczenia bez dokładnego zrozumienia, kto i dlaczego odziedziczy moją klasę.
źródło
Wszystkie trzy poziomy dostępu mają przypadek użycia, brak OOP byłby niekompletny. Zwykle tak
Odchodzisz od tego ogólnego schematu tylko wtedy, gdy istnieje ku temu dobry powód ™ . Uważaj na „to ułatwi moje życie, kiedy będę mieć swobodny dostęp do niego z zewnątrz” (a tutaj na zewnątrz także podklasy). Kiedy wdrażam hierarchie klas, często zaczynam od klas, które nie mają chronionych członków, dopóki nie przechodzę do ich podklasowania / rozszerzania / specjalizacji, stając się podstawowymi klasami frameworka / zestawu narzędzi i czasami przenosząc część ich oryginalnej funkcjonalności o jeden poziom wyżej.
źródło
Być może bardziej interesujące pytanie dotyczy tego, dlaczego potrzebny jest jakikolwiek inny rodzaj pola niż prywatny. Gdy podklasa musi wchodzić w interakcję z danymi nadklasy, czynność ta bezpośrednio tworzy bezpośrednie połączenie między nimi, podczas gdy stosowanie metod zapewniających interakcję między nimi pozwala na poziom pośredni, który umożliwia wprowadzenie zmian w nadklasa, która w innym przypadku byłaby bardzo trudna.
Wiele języków (np. Ruby i Smalltalk) nie udostępnia pól publicznych, dlatego programiści nie mogą zezwalać na bezpośrednie łączenie z implementacjami swoich klas, ale dlaczego nie pójść dalej i mieć tylko pola prywatne? Nie nastąpiłaby utrata ogólności (ponieważ nadklasa zawsze może zapewniać chronione akcesoria dla podklasy), ale zapewniłaby, że klasy zawsze miałyby co najmniej niewielki stopień izolacji od swoich podklas. Dlaczego nie jest to bardziej powszechny projekt?
źródło
Wiele dobrych odpowiedzi tutaj, ale i tak wrzucę dwa centy. :-)
Prywatne jest dobre z tego samego powodu, dla którego dane globalne są złe.
Jeśli klasa deklaruje dane jako prywatne, to absolutnie wiesz, że jedynym kodem, który ma problemy z tymi danymi, jest kod w klasie. Kiedy pojawia się błąd, nie musisz przeszukiwać całego stworzenia, aby znaleźć każde miejsce, które może zmienić te dane. Wiesz, że jest w klasie. Po wprowadzeniu zmiany w kodzie i zmianie sposobu korzystania z tego pola nie trzeba śledzić wszystkich potencjalnych miejsc, które mogłyby korzystać z tego pola, i badać, czy planowana zmiana je złamie. Wiesz, że jedyne miejsca są w klasie.
Miałem wiele, wiele razy, że musiałem wprowadzać zmiany do klas, które są w bibliotece i są używane przez wiele aplikacji, i muszę bardzo ostrożnie stąpać, aby upewnić się, że nie zepsuję aplikacji, o których nic nie wiem. Im więcej danych publicznych i chronionych, tym większy potencjał problemów.
źródło
Myślę, że warto wspomnieć o kilku odmiennych opiniach.
Teoretycznie dobrze jest mieć kontrolowany poziom dostępu ze wszystkich powodów wymienionych w innych odpowiedziach.
W praktyce zbyt często podczas przeglądania kodu widzę osoby (lubiące korzystać z prywatnych), zmieniające poziom dostępu z prywatnego -> chroniony i niezbyt często z chronionego -> publiczny. Prawie zawsze zmiana właściwości klasy wiąże się z modyfikacją ustawiaczy / getterów. To zmarnowało wiele mojego czasu (przegląd kodu) i ich (zmiana kodu).
Denerwuje mnie również to, że ich klasy nie są zamknięte do modyfikacji.
To było z wewnętrznym kodem, w którym zawsze możesz go zmienić, jeśli potrzebujesz. Gorzej jest z kodem innej firmy, gdy zmiana kodu nie jest taka łatwa.
Ilu programistów uważa, że to kłopot? Cóż, ilu używa języków programowania, które nie mają prywatnego? Oczywiście ludzie nie tylko używają tych języków, ponieważ nie mają prywatnych specyfikatorów, ale pomaga uprościć języki, a prostota jest ważna.
Imo jest bardzo podobny do pisania dynamicznego / statycznego. Teoretycznie pisanie statyczne jest bardzo dobre. W praktyce uniemożliwia to tylko jak 2% błędów nadmierną Efektywność Dynamiczny piszą ... . Korzystanie z trybu prywatnego prawdopodobnie zapobiega mniejszym błędom.
Uważam, że zasady SOLID są dobre. Chciałbym, żeby ludzie dbali o nie bardziej, niż dbali o stworzenie klasy publicznej, chronionej i prywatnej.
źródło
Chciałbym również dodać kolejny praktyczny przykład, dlaczego
protected
to nie wystarczy. Na mojej uczelni pierwsze lata podejmują projekt, w którym muszą opracować wersję komputerową gry planszowej (do której później opracowano sztuczną inteligencję i jest ona połączona z innymi graczami przez sieć). Dostarczono im częściowy kod umożliwiający rozpoczęcie pracy, w tym środowisko testowe. Niektóre właściwości głównej klasy gry są ujawnione wprotected
taki sposób, że klasy testowe, które rozszerzają tę klasę, mają do nich dostęp. Ale te pola nie są poufnymi informacjami.Jako TA dla jednostki często widzę, że uczniowie po prostu tworzą cały swój dodany kod
protected
lubpublic
(być może dlatego, że widzieli inneprotected
i innepublic
rzeczy i zakładali, że powinni pójść za nimi). Pytam ich, dlaczego ich poziom ochrony jest niewłaściwy, a wielu nie wie dlaczego. Odpowiedź jest taka, że wrażliwe informacje, które ujawniają w podklasach, oznaczają, że inny gracz może oszukiwać, po prostu rozszerzając tę klasę i uzyskując dostęp do bardzo wrażliwych informacji w grze (zasadniczo ukrytej lokalizacji przeciwników, myślę, że podobnie jak by to było, gdybyś mogli zobaczyć elementy przeciwników na planszy pancerników, powiększając niektóre klasy). To sprawia, że ich kod jest bardzo niebezpieczny w kontekście gry.Poza tym istnieje wiele innych powodów, aby zachować prywatność nawet dla swoich podklas. Może to być ukrywanie szczegółów implementacji, które mogłyby zepsuć poprawne działanie klasy, jeśli zostaną zmienione przez kogoś, kto niekoniecznie wie, co robią (głównie myśląc o innych ludziach używających twojego kodu tutaj).
źródło
Prywatne metody / zmienne będą na ogół ukryte przed podklasą. To może być dobra rzecz.
Prywatna metoda może przyjmować założenia dotyczące parametrów i pozostawić sprawdzanie poprawności dzwoniącemu.
Metoda chroniona powinna sprawdzać poprawność danych wejściowych.
źródło
„prywatny” oznacza: Nie jest przeznaczony do zmiany ani dostępu dla kogokolwiek poza samą klasą. Nieprzeznaczony do zmiany lub dostępu przez podklasy. Podklasy? Jakie podklasy? Nie należy tego podklasować!
„chroniony” oznacza: przeznaczony wyłącznie do zmiany lub dostępu przez klasy lub podklasy. Prawdopodobne wnioskowanie, które należy podklasować, w przeciwnym razie dlaczego „chroniony”, a nie „prywatny”?
Jest tutaj wyraźna różnica. Jeśli zrobię coś prywatnego, powinieneś trzymać od tego brudne palce. Nawet jeśli jesteś podklasą.
źródło
Niektóre rozumowanie o
private
vs.protected
metod :private
metody zapobiegają ponownemu użyciu kodu. Podklasa nie może użyć kodu w metodzie prywatnej i może wymagać ponownego zaimplementowania go - lub ponownej implementacji metod, które pierwotnie zależą od metody prywatnej & c.Z drugiej strony każdą metodę, która nie
private
jest postrzegana jako interfejs API dostarczony przez klasę do „świata zewnętrznego”, w tym sensie, że podklasy innych firm również są uważane za „świat zewnętrzny”, jak ktoś inny sugerował w swojej odpowiedzi już.Czy to źle? - Nie wydaje mi się.
Oczywiście (pseudo-) publiczny interfejs API blokuje pierwotnego programistę i utrudnia refaktoryzację tych interfejsów. Ale patrząc na drugą stronę, dlaczego programista nie powinien projektować własnych „szczegółów implementacji” w sposób tak czysty i stabilny jak jego publiczny interfejs API? Czy powinien to
private
zrobić, aby nie był niechętny do konstruowania swojego „prywatnego” kodu? Myślisz, że może to później posprząta, bo nikt tego nie zauważy? - Nie.Programiści powinni również przemyśleć trochę swój „prywatny” kod, aby ustrukturyzować go w sposób, który pozwala, a nawet promuje ponowne wykorzystanie jego jak największej liczby. Wówczas części nieprywatne mogą nie stać się tak dużym obciążeniem w przyszłości, jak niektórzy się obawiają.
Wiele (ramowej) kodu widzę przyjmuje niespójne stosowanie
private
:protected
metody non-końcowe, które ledwo robić nic więcej niż delegowanie do prywatnej metody jest powszechnie spotykane.protected
, nie ostateczne metody, których umowa może zostać zrealizowana jedynie poprzez bezpośredni dostęp do pól prywatnych.Te metody nie mogą być logicznie zastąpione / ulepszone, chociaż technicznie nie ma nic, co by uczyniło to (kompilatorem) oczywistym.
Chcesz możliwości rozszerzenia i dziedziczenia? Nie twórzcie swoich metod
private
.Nie chcesz zmienić niektórych zachowań twojej klasy? Twórz swoje metody
final
.Czy naprawdę nie można wywołać metody poza określonym, dobrze określonym kontekstem? Udostępnij swoją metodę
private
i / lub zastanów się, jak udostępnić wymagany, dobrze zdefiniowany kontekst do ponownego użycia za pomocą innejprotected
metody opakowania.Dlatego
private
zalecam oszczędne używanie . I nie mylićprivate
zfinal
. - Jeśli implementacja metody jest istotna dla ogólnego kontraktu klasy i dlatego nie może być zastąpiona / zastąpiona, zrób tofinal
!Dla pól
private
nie jest naprawdę źle. Tak długo, jak pole (pola) można rozsądnie „wykorzystać” za pomocą odpowiednich metod (to nie jestgetXX()
lubsetXX()
!).źródło
private
vsprotected
oryginalne pytanie, daje błędne informacje ( „używaćprivate
oszczędnie”?) I jest sprzeczne z ogólnym konsensusu w sprawie projektu OO. Korzystanieprivate
nie ma nic wspólnego z ukrywaniem niechlujnego kodu.private
pomaga utrzymać API w czystości.Prywatne : gdy masz coś, co nigdy nie będzie przydatne dla żadnej podklasy do wywołania lub zastąpienia.
Chroniony : gdy masz coś, co ma implementację / stałą dla podklasy.
Przykład:
źródło
Trudno mi było zrozumieć tę sprawę, dlatego chciałbym podzielić się częścią mojego doświadczenia:
$classInstance->field
. I sztuczka polegająca na tym, że „to jest to”. Dzieci twojej klasy będą miały do niej pełny dostęp, ponieważ jest to ich prawowita część wewnętrzna.AKTUALIZACJA: praktyczny przykład prawdziwego zadania, które rozwiązałem. Oto on: masz token, taki jak USB lub LPT (tak było w moim przypadku) i masz oprogramowanie pośrednie. Token prosi o podanie kodu PIN, otwiera się, jeśli jest poprawny, i możesz wysłać zaszyfrowaną część i liczbę kluczy do rozszyfrowania. Klucze są przechowywane w tokenie, nie można ich odczytać, należy ich używać. I były tymczasowe klucze do sesji, podpisane kluczem w tokenie, ale przechowywane w samym oprogramowaniu pośrednim. Klawisz tymczasowy nie miał przeciekać gdziekolwiek na zewnątrz, tylko po to, aby istniał na poziomie kierowcy. I użyłem prywatnych pól do przechowywania tego klucza tymczasowego i niektórych danych związanych z połączeniem sprzętowym. Dlatego żadne pochodne nie były w stanie korzystać nie tylko z interfejsu publicznego, ale także z niektórych chronionych„przydatne” podprogramy, które wykonałem dla zadania, ale nie udało mi się otworzyć sejfu za pomocą klawiszy i interakcji HW. Ma sens?
źródło