Dlaczego potrzebujemy zmiennych prywatnych?


210

Dlaczego potrzebujemy zmiennych prywatnych w klasach?

Każda książka o programowaniu, którą przeczytałem, mówi, że jest to zmienna prywatna, tak ją definiujesz, ale na tym się kończy.

Sformułowanie tych wyjaśnień zawsze wydawało mi się, że naprawdę mamy kryzys zaufania do naszego zawodu. Wyjaśnienia zawsze brzmiały tak, jakby inni programiści zepsuli nasz kod. Istnieje jednak wiele języków programowania, które nie mają zmiennych prywatnych.

  1. Czemu pomagają zmienne prywatne?

  2. Jak decydujesz, czy dana nieruchomość powinna być prywatna, czy nie? Jeśli domyślnie każde pole MUSI być prywatne, to dlaczego w klasie są publiczni członkowie danych?

  3. W jakich okolicznościach należy podać zmienną do wiadomości publicznej?


9
Twoje pytanie brzmi bardzo agnostycznie, ale oznaczyłeś je jako java i c ++. Jeśli interesują Cię perspektywy spoza tych dwóch języków, prawdopodobnie powinieneś to powiedzieć.
James

8
Dla przypomnienia, utworzenie prywatnej metody nie zwiększa „bezpieczeństwa”. Inne części aplikacji mogą nadal uzyskiwać dostęp do prywatnych członków za pomocą refleksji.
kba

3
Wykorzystanie i różnica między zmiennymi prywatnymi i publicznymi oraz dlaczego je mamy, można zrozumieć tylko w kontekście ogólnych zasad obiektowych. Nie można tego zrozumieć oddzielnie. Prawdopodobnie trzeba na to spojrzeć z tej perspektywy, sprawy mogą się wyjaśnić.
Nazar Merza

1
możliwy duplikat uzasadnienia
Getters

3
Jeśli złapiesz kogoś, kto używa pasa bezpieczeństwa w samochodzie, powinieneś zabrać mu prawo jazdy, ponieważ oczywiście nie ufają własnym umiejętnościom prowadzenia pojazdu.
gnasher729

Odpowiedzi:


307

To nie tyle kwestia zaufania, co kwestia zarządzania złożonością.

Do członka publicznego można uzyskać dostęp spoza klasy, co ze względów praktycznych oznacza „potencjalnie w dowolnym miejscu”. Jeśli coś pójdzie nie tak z polem publicznym, winowajcą może być gdziekolwiek, więc aby wyśledzić błąd, być może będziesz musiał spojrzeć na całkiem sporo kodu.

Natomiast do członka prywatnego można uzyskać dostęp tylko z tej samej klasy, więc jeśli coś pójdzie nie tak, zwykle jest tylko jeden plik źródłowy do obejrzenia. Jeśli masz milion wierszy kodu w swoim projekcie, ale twoje klasy są małe, może to zmniejszyć wysiłek w zakresie śledzenia błędów o 1000 razy.

Kolejna zaleta związana jest z koncepcją „sprzęgania”. Publiczna członkiem mklasy A, który jest używany przez inną klasę Bwprowadza zależność: jeśli zmieni msię A, trzeba także sprawdzić zwyczajów mw B. Co gorsza, nic w klasie nie Amówi, gdzie mjest używany, więc ponownie musisz przeszukać całą bazę kodów; jeśli piszesz bibliotekę, musisz nawet upewnić się, że kod znajduje się na zewnątrztwój projekt się nie psuje z powodu twojej zmiany. W praktyce biblioteki mają tendencję do trzymania się oryginalnych sygnatur metod tak długo, jak to możliwe, bez względu na to, jak bolesne, a następnie wprowadzają blok przełomowych zmian wraz z aktualizacją głównej wersji. Natomiast członkowie prywatni mogą od razu wykluczyć zależności - nie można uzyskać do nich dostępu z zewnątrz, więc wszystkie zależności są zawarte w klasie.

W tym kontekście „inni programiści” obejmują waszą przyszłość i przeszłość. Możliwe, że wiesz już, że nie powinieneś robić tej rzeczy X ze zmienną Y, ale na pewno zapomnisz trzy miesiące później, gdy klient pilnie potrzebuje twojej implementacji funkcji i zastanawiasz się, dlaczego robisz przerwy X Y w niejasny sposób.

Tak więc, kiedy powinieneś uczynić rzeczy prywatnymi: Powiedziałbym, że domyślnie ustaw wszystko na prywatne, a następnie ujawnij tylko te części, które absolutnie muszą być publiczne. Im więcej możesz ustawić jako prywatne, tym lepiej.


24
+1 za przejście do sedna problemu, chociaż osobiście uważam, że mój kod jest łatwiejszy do utrzymania, gdy przestałem przechodzić przez obręcze, aby upewnić się, że często używana zmienna pozostaje prywatna. Jasne, że w przyszłości może pojawić się błąd, ale jest o 60 mniej wierszy kodu do przeskoczenia i mniej zmiennych i funkcji do rozruchu;)
Jeffrey Sweeney

48
Święty Graal współczesnych komputerów ogranicza złożoność.

1
Zawsze lubię mówić, że częścią debugowania jest nie tylko bezpośrednie dążenie do „tego, co poszło nie tak”, ale także podjęcie ronda, aby dowiedzieć się, „co nie poszło źle”, i skoncentrowanie mojego dochodzenia na tym, co pozostało. Jeśli uda mi się poprosić kompilator o pomoc w takich narzędziach, jak zmienne prywatne, w celu zdefiniowania „tego, co nie mogło się zdarzyć”, oszczędza mi to mnóstwo czasu. Tylko w rzadkich przypadkach, gdy udowodnię, że to, co poszło nie tak, nie mogło się zdarzyć, muszę zagłębić się w bardziej przerażające założenia, jak na przykład przekroczenie bufora zastępujące moje prywatne dane.
Cort Ammon

2
Dokładnie to. Kiedy ludzie słyszą „ukrywanie informacji”, myślą, że powinni używać zmiennych prywatnych do takich rzeczy, jak klucze szyfrowania, dane uwierzytelniające bazy danych itp.
Wayne Werner

2
@AdamZerner patrz „Powiedz, nie pytaj” ( martinfowler.com/bliki/TellDontAsk.html ) o tym, czy w pierwszej kolejności masz getters / setters - ale poza tym tak, ponieważ powinieneś mieć swobodę zmiany wewnętrznej reprezentacji wartości w dowolnym momencie chciałbyś. Jak zawsze, są wyjątki ... (np. DTO)
podwójnyYou 18'18

111

Zmienne prywatne pomagają zapobiegać uzależnieniu ludzi od niektórych części twojego kodu. Powiedzmy, że chcesz zaimplementować pewną strukturę danych. Chcesz, aby użytkownicy Twojej struktury danych nie dbali o to, jak ją zaimplementowałeś, ale po prostu używaj implementacji poprzez dobrze zdefiniowany interfejs. Powodem jest to, że jeśli nikt nie zależy od Twojej implementacji, możesz ją zmienić w dowolnym momencie. Na przykład możesz zmienić implementację zaplecza, aby poprawić wydajność. Wszyscy inni programiści, którzy polegali na twoich implementacjach, zepsują się, podczas gdy użytkownicy interfejsu będą w porządku. Elastyczność zmiany implementacji bez wywierania wpływu na użytkowników klasy jest ogromną korzyścią wynikającą z używania zmiennych prywatnych (a szerzej - enkapsulacji ).

Nie jest to tak naprawdę „kryzys zaufania”. Jeśli podasz część danych do wiadomości publicznej, nie możesz upewnić się, że nikt nie jest od niej zależny. Często bardzo wygodnie jest polegać na jakiejś zmiennej specyficznej dla implementacji, zamiast przechodzić przez interfejs publiczny, szczególnie w dobie ostatecznego terminu. Ponadto programiści nie zawsze zdają sobie sprawę, że są zależni od czegoś, co może się zmienić.

Mam nadzieję, że tego rodzaju odpowiedzi na pozostałe pytania. Wszystkie szczegóły implementacji powinny być prywatne, a część publiczna powinna być małym, zwięzłym, dobrze zdefiniowanym interfejsem do korzystania z twojej klasy.


24
IMO dotyczy także komunikacji między autorem lib a konsumentem lib. Interfejs publiczny przypomina „używaj tego”, a osoby prywatne - „nie używaj tego”, z tym wyjątkiem, że w Javie naprawdę nie można go przypadkowo użyć, jeśli jest prywatny, dzięki czemu jest bezpieczniejszy i bardziej przejrzysty.
chakrit

5
@chakrit i inni: Pamiętaj, że ci, którzy naprawdę chcą korzystać z twoich prywatnych pól i metod, mogą to zrobić (poprzez refleksję). privatejest mniejszy niż „nieprzeznaczony głównie dla bezpieczeństwa”, nie zapewnia „bezpieczeństwa”, o którym można mówić. To tylko silna wskazówka (dostarczana przez kompilator), aby nie uzyskiwać do niej dostępu.

@ delnan zwróć uwagę na wyrażenie „przypadkiem” tak, może powinienem być bardziej zrozumiały.
chakrit

@chakrit Tak, nie chciałem sugerować, że się mylisz. Chciałem tylko promować ten punkt.

1
@delnan: Prywatne pola, w niektórych językach, zapewniają pewne formy bezpieczeństwa. Na przykład zobacz odpowiedź Erica Lipperta: Czy poziomy dostępu i modyfikatory (prywatne, zapieczętowane itp.) Służą celom bezpieczeństwa w języku C #? .
Brian

25

Słowem kluczowym jest tutaj enkapsulacja . W OOP chcesz używać zmiennych prywatnych w celu wymuszenia właściwego hermetyzacji obiektów / klas.

Podczas gdy inni programiści nie chcą cię zdobyć, wchodzą w interakcje z twoim kodem. Jeśli nie ustawisz zmiennej jako prywatną, mogą oni odwoływać się do niej we własnym kodzie, nie chcąc w ogóle wyrządzać żadnej szkody. Jeśli jednak musisz wrócić do klasy i coś zmienić, nie wiesz już, kto i gdzie używa tej zmiennej. Celem enkapsulacji jest jawne określenie zewnętrznego interfejsu klasy, abyś wiedział, że tylko te (zwykle) metody mogłyby być używane przez innych.

  1. Dlatego zmienne prywatne zapewniają, że odpowiednia zmienna pozostaje tylko w klasie definiującej. Jeśli musisz to zmienić, zmiana jest lokalna dla samej klasy.

  2. W tradycyjnych językach, takich jak C ++ lub Java, zwykle czynisz wszystko prywatnym i dostępnym tylko dla odpowiednich programów pobierających i ustawiających. Naprawdę nie musisz decydować zbyt wiele.

  3. Czasami np. w strukturze C ++ potrzebujesz klasy tylko jako sposobu na grupowanie kilku rzeczy razem. Rozważmy na przykład klasę wektor, który ma xi to ytylko atrybut. W takich przypadkach możesz zezwolić na bezpośredni dostęp do tych atrybutów, ogłaszając je publicznie. W szczególności nie możesz się przejmować, jeśli jakiś kod poza modyfikuje obiekt twojej klasy, bezpośrednio zapisując nowe wartości w xlub y.

Jako dodatkowy punkt zwróć uwagę, że kwestia ta jest nieco inna w innych językach. Na przykład języki silnie zakorzenione w programowaniu funkcjonalnym podkreślają niezmienność danych, tzn. Wartości danych w ogóle nie można zmienić. W takich przypadkach nie musisz dbać o to, co inni programiści (a raczej ich kod) robią z Twoimi danymi. Po prostu nie mogą zrobić nic, co mogłoby wpłynąć na Twój kod, ponieważ wszystkie dane są niezmienne.

W tych językach otrzymujesz coś, co nazywa się zasadą jednolitego dostępu , gdzie celowo nie rozróżnia się metod takich jak gettery i setters, ale zapewnia bezpośredni dostęp do zmiennej / funkcji. Można więc powiedzieć, że prywatne deklaracje są znacznie bardziej popularne w scenariuszach obiektowych.

To pokazuje również, jak poszerzenie wiedzy o inne dziedziny sprawia, że ​​postrzegasz istniejące koncepcje w zupełnie nowy sposób.


1
+1 „Podczas gdy inni programiści nie chcą cię zdobyć, wchodzą w interakcje z twoim kodem.” Programiści używający twojego kodu nie są z natury źli. Korzystając ze zmiennych prywatnych, upewniasz się, że (i Ty, w przyszłości), nie ucierpi na tym kod. Pomaga także zaprojektować lepszy interfejs API i udokumentować go.
szalski

7

Zmienne prywatne zapewniają, że późniejsze odwołania poza zakresem obiektu lub funkcji nie wpływają przypadkowo na inne zmienne. W przypadku dużych projektów programowych może to pomóc uniknąć wielu interesujących problemów (które zwykle nie są wychwytywane przez kompilator).

Na przykład prototypowe języki, takie jak Javascript, pozwalają użytkownikom na stosowanie zmiennych według własnego uznania:

function SomeObject() {
    this.a = 2; //Public (well, actually protected) variable

    this.showA = function() {
        alert(this.a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 3. Uh oh!

Gdyby ta zmienna była prywatna, nie można jej zmienić z zewnątrz:

function SomeObject() {
    var a = 2; //Private variable

    this.showA = function() {
        alert(a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 2

To powiedziawszy, nie wszystkie zmienne muszą być prywatne, a nadmierne użycie zmiennych prywatnych może w rzeczywistości uczynić kod bardziej kłopotliwym. Trywialne pola, które nie mają poważnego wpływu na obiekt, nie potrzebują get()i nie wymagają set()metod.

Zmienne prywatne ułatwiają także rozszerzanie kodu w przyszłości, bez polegania na obszernej dokumentacji tego, co robi wiele zmiennych publicznych. Zagrożenie przypadkowym uszkodzeniem funkcji jest mniejsze, jeśli można zastąpić mniej zmiennych.

Zmiennych publicznych należy używać, gdy obiekt / funkcja będzie uzyskiwać dostęp do innych obiektów / funkcji, ponieważ z reguły zmienne prywatne nie mogą tego zrobić. Możesz mieć od kilku do kilku publicznych zmiennych, i nie jest źle, jeśli używasz ich poprawnie.


Nie jest oczywiste, dlaczego alarmowanie 3 byłoby „och, och!” w tym przypadku. Może to właśnie chciał programista.
immibis

@immibis Być może, a może powinienem był rozwinąć więcej odpowiedzi. Ale dostęp do właściwości może otworzyć drzwi do naruszenia niektórych zasad OOP, takich jak zasada otwartego zamknięcia lub LoD, ponieważ potencjalnie ujawniasz szczegóły implementacji. „Oczywiście, zależy to od tego, czym dokładnie jest ta właściwość. Większość języków używa obiektów jako odniesień, a kiedy odniesienia do obiektów są przekazywane, a inni deweloperzy cicho zmieniają właściwości, NAPRAWDĘ trudno jest debugować. IMO jest znacznie łatwiejsze i bardziej rozszerzalne do pracy z metodami, jeśli masz instancję klasy.
Jeffrey Sweeney

7

Istnieje kilka dobrych odpowiedzi wskazujących na korzyści dla przyszłych opiekunów i użytkowników klasy. Istnieją jednak również zalety oryginalnego projektu. Zapewnia wyraźny punkt rozgraniczający pomiędzy tym, kiedy twoim celem jest ułatwienie sobie, a kiedy twoim celem jest ułatwienie użytkownikowi klasowemu. Kiedy wybierasz pomiędzy publicznym i prywatnym, sygnał do twojego mózgu, aby przejść do jednego lub drugiego trybu, i kończy się na lepszym API.

Nie jest tak, że języki bez prywatności uniemożliwiają taki projekt, a jedynie mniej prawdopodobne. Zamiast zachęty do napisania czegoś takiego foo.getBar(), ludzie są skłonni myśleć, że getter nie jest konieczny, ponieważ łatwiej jest pisać foo.bar, ale wtedy ta decyzja nie zostanie ponownie podjęta, gdy później skończysz z dłuższymi potworami, takimi jak obj.container[baz].foo.bar. Programiści, którzy nigdy nie pracowali w bardziej surowym języku, mogą nawet nie zobaczyć, co jest z tym nie tak.

Dlatego w językach bez prywatności ludzie często przyjmują symulujące je standardy nazewnictwa, takie jak przygotowywanie podkreślenia dla wszystkich „prywatnych” członków. Jest to przydatny sygnał, nawet jeśli język go nie wymusza.


3

Wszystkie zmienne powinny być prywatne, chyba że absolutnie muszą być publiczne (co prawie nigdy nie należy, należy używać właściwości / getterów i setterów).

Zmienne w dużej mierze zapewniają stan obiektu, a zmienne prywatne uniemożliwiają innym wejście i zmianę stanu obiektu.


5
Zbyt wąski obraz tematu. Są przypadki, w których publiczny dostęp do pola jest gwarantowany, a nawet preferowany
Roland Tepp

Z pewnością można zaprojektować obiekty, których stanu nie można zmienić (obiekty niezmienne), ale nie jest to ogólna zasada stosowana do wszystkich klas. Z mojego doświadczenia wynika, że ​​większość obiektów bardzo ułatwia innym zmianę stanu obiektu.
David K

1
@DavidK Być może to, co BBB miał na myśli, to to, że „zmienne prywatne uniemożliwiają innym wejście i masową zmianę stanu obiektu”. Metody publiczne mogą zmieniać stan prywatny obiektu, ale tylko w sposób niezbędny i spójny dla funkcjonowania obiektu.
Max Nanasy,

@Max Nanasy: Tak, można kontrolować, jak zmienia się stan, gdy oferuje się tylko metody w interfejsie publicznym. Na przykład może istnieć relacja między elementami, która musi być spełniona, aby obiekt był „samowystarczalny”, a można zezwolić na zmianę stanu samozgodnego tylko na inny stan samozgodny. Jeśli wszystkie te zmienne są publiczne, nie możesz tego egzekwować. Ale mogą również istnieć obiekty, w których nie chcesz zezwalać na jakiekolwiek zmiany, dlatego ważne jest, aby wyjaśnić, o której z tych rzeczy mówimy.
David K

2
  • Czemu pomagają zmienne prywatne?

Chodzi o wyjaśnienie, jakie właściwości i metody są interfejsem, a które są podstawową funkcjonalnością. Metody publiczne / właściwości dotyczą innego kodu, często innego kodu programisty używającego twoich obiektów. Nigdy nie pracowałem w zespołach powyżej 100 nad tym samym projektem, ale z mojego doświadczenia, że ​​może składać się z 3–5 zespołów z maksymalnie 20 innymi programistami używającymi rzeczy, które napisałem, inne obawy wydają się głupie.

Uwaga: Jestem przede wszystkim programistą JavaScript. Zasadniczo nie martwię się o to, że inni programiści przeglądają mój kod i działam z pełną świadomością, że mogą po prostu przedefiniować moje rzeczy w dowolnym momencie. Zakładam, że są wystarczająco kompetentni, aby wiedzieć, co robią w pierwszej kolejności. Jeśli nie, to raczej nie będę pracował w zespole, który nie korzysta z kontroli źródła.

  • Jak decydujesz, czy określony zestaw właściwości powinien być prywatny, czy nie? Jeśli domyślnie każde pole MUSI być prywatne, to dlaczego w klasie są publiczni członkowie danych?

Kiedyś myślałem, że głupie jest umieszczanie osób pobierających i ustawiających w prywatnych obiektach, kiedy tak naprawdę nie przeprowadza się żadnej weryfikacji ani innego specjalnego traktowania właściwości, które mają zostać ustawione. Nadal nie uważam, że to zawsze jest konieczne, ale jeśli masz do czynienia z dużą skalą, dużą złożonością, ale co najważniejsze, wiele innych deweloperów polegających na tym, że twoje obiekty zachowują się w spójny sposób, może być użyteczne spójny i jednolity sposób. Gdy ludzie widzą metody nazywane getThatisetThat, dokładnie wiedzą, jakie są intencje, i mogą pisać swoje przedmioty, by wchodzić w interakcje z twoimi, oczekując, że zawsze dostaną pomidory, a nie tomahta. Jeśli tego nie zrobią, będą wiedzieli, że twój obiekt daje im coś, czego prawdopodobnie nie powinien, co oznacza, że ​​pozwala innemu obiektowi na zrobienie czegoś z tymi danymi, czego prawdopodobnie nie powinien. Możesz to kontrolować w miarę potrzeby.

Inną dużą zaletą jest to, że łatwiej jest przekazywać lub interpretować wartości obiektów inaczej niż obiekt pobierający lub ustawiający w oparciu o pewien kontekst stanu zmiennego. Ponieważ uzyskują dostęp do twoich metod za pomocą metody, o wiele łatwiej jest zmienić sposób, w jaki obiekt działa później, bez łamania innego kodu, który od niego zależy. Ważną zasadą jest to, że tylko twój obiekt faktycznie zmienia dane, za które zostałeś odpowiedzialny. Jest to szczególnie ważne dla luźnego powiązania kodu, co jest ogromną wygraną pod względem przenośności i łatwości modyfikacji.

  • W jakich okolicznościach należy podać zmienną do wiadomości publicznej?

Dzięki funkcjom pierwszej klasy (możesz przekazywać funkcje jako argumenty), nie mogę wymyślić wielu innych ważnych powodów poza tym, że nie jest to szczególnie konieczne w przypadku mniejszych projektów. Bez tego przypuszczam, że moglibyście mieć członków, którzy są intensywnie i regularnie przetwarzani przez inne obiekty w stopniu, w jakim ciągłe wywoływanie get i ustawianie na obiekcie, który tak naprawdę nie dotyka tych danych, wydaje się nieco okrutne. sam by mnie zastanawiał, dlaczego obiekt był odpowiedzialny za te dane. Ogólnie rzecz biorąc, chciałbym ponownie zbadać moją architekturę pod kątem wad, zanim zdecyduję, że publiczna właściwość danych jest konieczna. IMO, nie ma nic złego w języku pozwalającym robić coś, co zwykle jest złym pomysłem. Niektóre języki się nie zgadzają.


IMHO, nie ma nic szczególnie złego w posiadaniu klasy publicznej, której jedynym celem jest ujawnianie zmiennych publicznych. Rzeczywiście, JVM posiada szereg wbudowanych klas w tym celu: int[], double[], Object[], itd. Trzeba jednak być bardzo ostrożnym, jak jeden naraża wystąpienia takiej klasy. Znaczenie void CopyLocationTo(Point p);[przyjmowanie Pointod dzwoniącego] jest wyraźniejsze niż Point location(), ponieważ nie jest jasne, jaki wpływ Point pt = foo.location(); pt.x ++;będzie miał na lokalizację foo.
supercat

2

Zobacz mój post na powiązane pytanie dotyczące SO .

Krótko mówiąc, zmienny zakres pozwala pokazać konsumentom twojego kodu, z czym powinni i nie powinni zadzierać. Zmienna prywatna może przechowywać dane, które zostały „sprawdzone” za pomocą ustawiacza właściwości lub metody przetwarzania, aby zapewnić spójność całego obiektu. Bezpośrednia zmiana wartości zmiennej prywatnej może spowodować, że obiekt stanie się niespójny. Ustawiając to jako prywatne, ktoś musi naprawdę ciężko pracować i mieć naprawdę wysokie uprawnienia czasu wykonywania, aby to zmienić.

Właściwe określanie zakresu elementów jest zatem kluczowe w kodzie samodokumentującym.


2

Opowiem o wartości enkapsulacji z innej perspektywy na prawdziwym przykładzie. Jakiś czas temu (wczesne lata 80.) napisano grę dla Radio Shack Color Computer o nazwie Dungeons of Daggorath. Kilka lat temu Richard Hunerlach przeniósł go z papierowego asemblera do C / C ++ ( http://mspencer.net/daggorath/dodpcp.html ). Jakiś czas później dostałem kod i zacząłem go ponownie rozkładać na czynniki, aby zapewnić lepszą enkapsulację ( http://dbp-consulting.com/stuff/ ).

Kod został już podzielony na różne obiekty do obsługi planowania, wideo, danych wejściowych użytkownika, tworzenia lochów, potworów itp., Ale z pewnością można stwierdzić, że został przeniesiony z asemblera. Moim największym zadaniem było zwiększenie enkapsulacji. Rozumiem przez to różne fragmenty kodu, aby pozbyć się nosa ze swojej działalności. Na przykład było wiele miejsc, które bezpośrednio zmieniałyby zmienne wideo, aby uzyskać pewien efekt. Niektórzy robili to za pomocą sprawdzania błędów, inni nie, niektórzy mieli subtelnie różne wyobrażenia o tym, co znaczy ta zmiana. Dużo dublowano kod. Zamiast tego sekcja wideo musiała mieć interfejs do wykonania pożądanych zadań, a kod do zrobienia tego mógł być w jednym miejscu, jednym pomyśle, jednym miejscu do debugowania. Takie rzeczy szalały.

Gdy kod zaczął się drażnić, błędy, które nawet nie zostały zdiagnozowane, zniknęły. Kod stał się wyższej jakości. Każde zadanie stało się obowiązkiem jednego miejsca w kodzie i było tylko jedno miejsce, aby je poprawnie wykonać. (Nadal znajduję więcej za każdym razem, gdy przeprowadzam kolejny kod).

Wszystko, co jest widoczne w kodzie, to interfejs użytkownika. Czy masz na myśli, czy tak nie jest. Jeśli ograniczysz widoczność tak bardzo, jak to możliwe, nie będziesz miał ochoty umieścić kodu w niewłaściwym miejscu. Widać, która część kodu jest odpowiedzialna za dane. To sprawia, że ​​projekt jest lepszy, czystszy, prostszy i bardziej elegancki.

Jeśli uczynisz obiekt odpowiedzialnym za własne dane i zapewnisz interfejsy wszystkim innym, którzy potrzebują, aby coś się wydarzyło, Twój kod stanie się DUŻO prostszy. Po prostu wypada. Masz małe proste procedury, które robią tylko jedną rzecz. Mniej złożoności == mniej błędów.


Ciężka równowaga między „swobodą użytkowników lib” a „mniejszym problemem dla nas”. Zaczynam wierzyć, że enkapsulacja jest lepsza w tym sensie, że zapobiegnę błędom w moim własnym kodowaniu i pomogę użytkownikom końcowym również w zapobieganiu błędom. Ale brak wolności może po prostu ich odłożyć, szukając alternatyw ... Być może kodowanie nie jest jeszcze używane, ale przewidywane funkcje za pomocą metod publicznych mogą pomóc w zrównoważeniu tego, ale wymaga więcej czasu.
Aquarius Power

Szkoda, że ​​zreformowanej wersji nie ma na
githubie

2

Nie ma to nic wspólnego z zaufaniem ani strachem przed atakami, chodzi wyłącznie o enkapsulację - nie zmuszanie niepotrzebnych informacji do użytkownika klasy.

Rozważmy stałe prywatne - nie powinny zawierać tajnych wartości (te powinny być przechowywane gdzie indziej), nie można ich zmienić, nie trzeba ich przekazywać do klasy (w przeciwnym razie musiałyby być publiczne). Jedynym możliwym zastosowaniem dla nich są stałe w INNYCH klasach. Ale jeśli to zrobisz, klasy te będą teraz zależeć od twojej klasy, aby wykonać pracę niezwiązaną z twoją klasą. Jeśli zmienisz stałą, inne klasy mogą się zepsuć. To źle z obu stron - jako pisarz swojej klasy, chcesz, aby wolność mogła zmieniać się tak bardzo, jak to możliwe, i nie chcesz martwić się o rzeczy poza twoją kontrolą. Konsument Twojej klasy chce być w stanie polegać na ujawnionych szczegółach twojej klasy, nie martwiąc się o to, że zmienisz go i złamiesz jego kod.

Konsument z twojej klasy chce wiedzieć wszystko, co jest potrzebne do interakcji z Twoją klasą i nie chce wiedzieć nic o twojej klasie, co nie zmienia tego, jak to robią: jest to bezużyteczna ciekawostka. Jeśli używałeś langauge z refleksją, jak często używałeś go, aby dowiedzieć się, jak niektóre klasy coś robią lub gdzie niespodziewanie rzuca wyjątek, ale po prostu nazwę prywatnych pól i metod? Założę się, że nigdy. Ponieważ nie masz pożytku z tej wiedzy.


1

Koncepcja OOP ma dziedziczenie ma jedną ze swoich funkcji (Java lub C ++). Jeśli więc odziedziczymy (co oznacza, że ​​uzyskamy dostęp do zmiennych odziedziczonej klasy), istnieje możliwość wpłynięcia na te zmienne. Musimy więc zdecydować, czy zmienne można zmienić, czy nie.

Tylko w tym celu używamy modyfikatorów dostępu w OOP. Jeden z modyfikatorów jest prywatny, co oznacza, że ​​może być dostępny tylko dla tej klasy. Żadna inna klasa nie może wpływać na te zmienne.

Jak wiemy, zabezpieczenie oznacza, że ​​dostęp do niego może uzyskać klasa, która odziedziczy.

Dlaczego istnieje koncepcja modyfikatora w OOP, wynika z tych powodów (każda klasa może uzyskać dostęp do innych zmiennych klas przy użyciu koncepcji OOP). Jeśli nie ma koncepcji modyfikatora, oznacza to, że byłoby to trudne podczas dziedziczenia klas lub używania innych koncepcji OOP.


1

Jak stwierdzili inni, prywatne zmienne są dobre, aby uniknąć niewłaściwego użycia prowadzącego obiekt do niespójnego statusu i trudnego do śledzenia błędów i nieprzewidzianych wyjątków.

Ale z drugiej strony to, co inni ignorowali, dotyczy pól chronionych.

Rozszerzona podklasa będzie miała pełny dostęp do chronionych pól, dzięki czemu obiekt będzie tak delikatny, jak gdyby takie pola były publiczne, ale ta kruchość jest ograniczona do rozszerzającej się klasy (chyba że jeszcze bardziej odsłoniłby takie pola).

Tak więc pola publiczne trudno uznać za dobre, a do tej pory jedynym powodem ich użycia są klasy używane jako parametr konfiguracyjny (bardzo prosta klasa z wieloma polami i bez logiki, więc klasa jest przekazywana jako parametr sam do jakaś metoda).

Ale z drugiej strony prywatne pola obniżają elastyczność kodu dla innych użytkowników.

Elastyczność a problemy, zalety i wady:

Obiekty tworzone przez Twój kod w klasie waniliowej z polami chronionymi są bezpieczne i ponosisz wyłączną odpowiedzialność.

Z drugiej strony, obiekty rozszerzające twoją klasę o pola chronione, tworzone przez użytkowników twojego kodu, są ich odpowiedzialnością, a nie twoją.

Zatem słabo udokumentowane chronione pola / metody lub jeśli użytkownicy tak naprawdę nie rozumieją, jak takie pola i metody powinny być używane, mają duże szanse na spowodowanie niepotrzebnych problemów dla siebie i dla ciebie.

Z drugiej strony, uczynienie większości rzeczy prywatnymi obniży elastyczność użytkowników, a nawet może odłożyć ich na bok, szukając utrzymywanych alternatyw, ponieważ mogą nie chcieć tworzyć i utrzymywać rozwidlenia tylko po to, aby coś się stało po swojemu.

Tak więc naprawdę ważna jest równowaga między prywatnym, chronionym i publicznym.

Teraz wybór między prywatnym a chronionym jest prawdziwym problemem.

Kiedy używać chronionego?

Za każdym razem, gdy rozumiesz, że pole może być bardzo elastyczne, należy je zakodować jako chronione. Ta elastyczność to: od uzyskania wartości zerowej (gdzie wartość zerowa jest zawsze sprawdzana i uznawana za prawidłowy stan bez zgłaszania wyjątków), do posiadania ograniczeń przed użyciem przez klasę ex. > = 0, <100 itd. I automatycznie ustawiane na wartości przekroczone / niedopełnione, wyświetlając co najwyżej komunikat ostrzegawczy.

Tak więc dla takiego chronionego pola można utworzyć getter i używać go tylko (zamiast bezpośrednio używać zmiennej field), podczas gdy inni użytkownicy mogą jej nie używać, na wypadek, gdyby chcieli większej elastyczności w swoim specyficznym kodzie, w moim przykładzie może to być : jeśli chcą, aby wartości ujemne działały poprawnie w ich rozszerzonej klasie.


-1

imo @tdammers nie ma racji i faktycznie wprowadza w błąd.

Istnieją zmienne prywatne, aby ukryć szczegóły implementacji. Twoja klasa Amoże używać arraydo przechowywania wyników. Jutro możesz użyć treelub priority queuezamiast niego. Wszyscy użytkownicy Twojej klasy potrzebują sposobu na wpisanie wyników i nazwisk addScore()oraz sposobu ustalenia, kto jest w pierwszej dziesiątce getTop(n).

Nie muszą uzyskiwać dostępu do podstawowej struktury danych. Brzmi wspaniale? Cóż, są pewne zastrzeżenia.

I tak nie powinieneś przechowywać wielu stanów, większość z nich nie jest potrzebna. Przechowywanie stanu skomplikuje Twój kod, nawet jeśli zostanie „posegregowany” do określonej klasy. Pomyśl o tym, ta zmienna prywatna prawdopodobnie uległa zmianie, ponieważ inny obiekt nazywał metodę tej klasy. Nadal musisz dowiedzieć się, kiedy i gdzie ta metoda została wywołana, a metodę publiczną można wywołać teoretycznie w dowolnym miejscu.

Najlepszą rzeczą, jaką możesz zrobić, to ograniczyć ilość stanu, który zawiera Twój program i używać czystych funkcji, jeśli to możliwe.


-1
  • Dostęp do zmiennej oznacza dostęp do jej wartości podczas działania programu, co powoduje, że zmienna prywatna chroni jej wartość podczas działania kodu.
  • Celem tak zwanego „ukrywania danych” jest ukrywanie danych wewnętrznych przed innymi klasami, które korzystają z tej klasy. Te inne klasy powinny mieć dostęp do zachowania tylko poprzez wywoływanie metod w klasie, a nie poprzez bezpośrednią zmianę wartości zmiennych.
  • Ustawiając zmienną jako prywatny element danych, możesz łatwiej upewnić się, że wartość nigdy nie będzie modyfikowana ani zmieniana. Z drugiej strony, jeśli zmienna jest publiczna, inna klasa może zmodyfikować lub zmienić wartość, która może spowodować awarię innych części kodu.

1
wydaje się, że nie oferuje to nic istotnego w porównaniu z punktami przedstawionymi i wyjaśnionymi w poprzednich 17 odpowiedziach
komnata

-4

Najpierw należy zrozumieć pojęcie programowania obiektowego. Ma abstrakcję, enkapsulację itp.

Abstrakcja - Rozumiesz logikę bez konieczności poznawania podkreślonych szczegółów implementacji.

Hermetyzacja - nie można zobaczyć podkreślonej implementacji obiektu. Tylko Ty możesz zobaczyć publiczny interfejs obiektu.

Teraz w konkretnej implementacji z jednym z programów obiektowych, takich jak C #, Java, C ++, możesz zaimplementować te koncepcje.

private - Implementacja, która powinna być ukryta przed światem zewnętrznym. Abyś mógł to zmienić i nie wpłynie to na użytkownika twojej klasy.

public - jest to interfejs, za pomocą którego można używać swojego obiektu.


1
chroniony - bezpośrednio dostępny dla podklas (przedłużaczy) (java).
Aquarius Power
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.