Czy kiedykolwiek powinieneś używać chronionych zmiennych członkowskich?

Czy należy kiedykolwiek używać chronionych zmiennych członkowskich? Jakie są zalety i jakie problemy może to spowodować?

Author: Jeff Atwood, 2008-08-31

10 answers

Czy należy używać chronionych zmiennych członkowskich?

Zależy jak wybredny jesteś w ukrywaniu stanu.

  • Jeśli nie chcesz wycieku wewnętrznego stanu, wtedy zadeklarowanie wszystkich zmiennych członkowskich jako prywatnych jest dobrym rozwiązaniem.
  • Jeśli nie zależy ci na tym, aby podklasy miały dostęp do stanu wewnętrznego, to protected jest wystarczająco dobre.

Jeśli pojawi się deweloper i podklasuje Twoją klasę, może to zepsuć, bo tego nie rozumie w pełni. W przypadku członków prywatnych, innych niż publiczny interfejs, nie widzą oni szczegółowych szczegółów dotyczących implementacji, co daje Ci elastyczność późniejszej zmiany.

 68
Author: Allain Lalonde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-29 13:19:10

Ogólne odczucie w dzisiejszych czasach jest takie, że powodują one nadmierne sprzężenie między klasami pochodnymi a ich bazami.

Nie mają szczególnej przewagi nad chronionymi metodami/właściwościami (Dawno, dawno temu mogły mieć niewielką przewagę wydajności), a także były używane bardziej w czasach, gdy modne było bardzo głębokie dziedziczenie, czym w tej chwili nie jest.

 29
Author: Will Dean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-31 18:42:08

Ogólnie rzecz biorąc, jeśli coś nie jest celowo postrzegane jako publiczne, robię to prywatnie.

Jeśli pojawi się sytuacja, w której potrzebuję dostępu do tej prywatnej zmiennej lub metody z klasy pochodnej, zmieniam ją z prywatnej na chronioną.

To się rzadko zdarza - naprawdę nie jestem fanem dziedziczenia, ponieważ nie jest to szczególnie dobry sposób na modelowanie większości sytuacji. W każdym razie, kontynuuj, nie martw się.

Powiedziałbym, że jest w porządku (i chyba najlepszy sposób na to) dla większość deweloperów.

Prostym faktem jest to, że, jeśli jakiś inny programista pojawi się rok później i zdecyduje, że potrzebuje dostępu do prywatnej zmiennej członkowskiej, po prostu zmieni kod, zmieni go na chroniony i będzie kontynuował swoją działalność.

Jedynymi prawdziwymi wyjątkami od tego są, jeśli jesteś w branży wysyłania binarnych dll w formie czarnej skrzynki do osób trzecich. Składa się w zasadzie z Microsoft, te " niestandardowe DataGrid Kontroluj dostawców, a może kilka innych dużych aplikacji, które wysyłają z bibliotekami rozszerzalności. Jeśli nie jesteś w tej kategorii, nie warto poświęcać czasu/wysiłku, aby martwić się o tego typu rzeczy.

 26
Author: Orion Edwards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-01 03:09:28

Ogólnie rzecz biorąc, zachowałbym Twoje chronione zmienne członkowskie do rzadkiego przypadku, w którym masz całkowitą kontrolę nad kodem, który ich używa. Jeśli tworzysz publiczne API, powiedziałbym nigdy. Poniżej będziemy odnosić się do zmiennej członkowskiej jako "właściwości" obiektu.

Oto co twoja superclass nie może zrobić po utworzeniu zmiennej member protected zamiast private-with-accessors:

  1. Leniwie twórz wartość w locie, gdy właściwość jest odczytywana. Jeśli dodajesz chronioną metodę getter, możesz leniwie utworzyć wartość i przekazać ją z powrotem.

  2. Wiedzieć, kiedy nieruchomość została zmodyfikowana lub usunięta. Może to wprowadzać błędy, gdy superclass przyjmuje założenia dotyczące stanu tej zmiennej. Wykonanie metody protected setter dla zmiennej utrzymuje tę kontrolę.

  3. Ustaw punkt przerwania lub dodaj wyjście debugowania, gdy zmienna jest odczytywana lub zapisywana.

  4. Zmień nazwę zmiennej członkowskiej bez przeszukiwania wszystkich kod, który może go użyć.

Ogólnie rzecz biorąc, myślę, że to rzadki przypadek, że zalecałbym utworzenie zmiennej chronionej. Lepiej poświęcić kilka minut na ujawnienie właściwości przez getters / setters niż kilka godzin później na śledzenie błędu w innym kodzie, który zmodyfikował chronioną zmienną. Nie tylko to, ale jesteś ubezpieczony przed dodaniem przyszłych funkcjonalności (takich jak leniwe ładowanie) bez łamania zależnego kodu. Trudniej zrobić to później niż zrobić to teraz.

 6
Author: Michael Bishop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-11 16:53:31

Na poziomie projektu może być właściwe użycie chronionej właściwości, ale dla implementacji nie widzę korzyści w mapowaniu tego do chronionej zmiennej członkowskiej zamiast metod accessor/mutator.

Chronione zmienne członkowskie mają znaczące wady, ponieważ skutecznie umożliwiają kodowi klienta (podklasie) dostęp do wewnętrznego stanu klasy bazowej. Zapobiega to efektywnemu utrzymywaniu niezmienników przez klasę bazową.

Z tego samego powodu, chronione zmienne członkowskie również znacznie utrudniają pisanie bezpiecznego kodu wielowątkowego, chyba że gwarantowana jest stała lub ograniczona do pojedynczego wątku.

Metody Accessor/mutator oferują znacznie większą stabilność API i elastyczność implementacji w trakcie konserwacji.

Ponadto, jeśli jesteś purystą OO, obiekty współpracują / komunikują się poprzez wysyłanie wiadomości, a nie odczytywanie / ustawianie stanu.

W zamian oferują bardzo niewiele korzyści. Niekoniecznie usunąłbym je z czyjś kod, ale sam go nie używam.

 6
Author: richj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-09 23:44:46

Kluczową kwestią dla mnie jest to, że gdy stworzysz zmienną chronioną, nie możesz pozwolić żadnej metodzie w twojej klasie, aby polegała na tym, że jej wartość mieści się w zakresie, ponieważ podklasa zawsze może umieścić ją poza zakresem.

Na przykład, jeśli mam klasę, która definiuje szerokość i wysokość obiektu renderowalnego, a ja chronię te zmienne, wtedy nie mogę przyjąć żadnych założeń nad (na przykład) proporcjami obrazu.

Krytycznie, mogę Nigdy dokonać tych założeń w żadnym wskaż od momentu wydania kodu jako biblioteki, ponieważ nawet jeśli zaktualizuję moje setery, aby zachować proporcje, nie mam gwarancji, że zmienne są ustawiane za pomocą seterów lub dostępne za pomocą getterów w istniejącym kodzie.

Ani żadna podklasa mojej klasy nie może zdecydować się na taką gwarancję, ponieważ nie mogą też wymuszać wartości zmiennych, , nawet jeśli jest to cały punkt ich podklasy .

Jako przykład:

  • mam klasę prostokąt z szerokość i wysokość są przechowywane jako chronione zmienne.
  • oczywistą podklasą (w moim kontekście) jest klasa "DisplayedRectangle", gdzie jedyną różnicą jest to, że ograniczam szerokość i wysokość do ważnych wartości dla wyświetlacza graficznego.
  • ale to jest teraz niemożliwe, ponieważ moja klasa DisplayedRectangle nie może naprawdę ograniczać tych wartości, ponieważ każda podklasa może zastąpić wartości bezpośrednio, a jednocześnie być traktowana jako DisplayedRectangle.

Ograniczając zmienne do prywatnych, mogę następnie wyegzekwować zachowanie, które chcę za pomocą setterów lub getterów.

 6
Author: deworde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-09 16:12:38

Przez większość czasu używanie protected jest niebezpieczne, ponieważ łamiesz nieco enkapsulację swojej klasy, która może zostać rozbita przez źle zaprojektowaną klasę pochodną.

Ale mam jeden dobry przykład: powiedzmy, że możesz jakiś rodzaj ogólnego kontenera. Ma wewnętrzną implementację i wewnętrzne Accesory. Ale musisz zaoferować co najmniej 3 publiczny dostęp do jego danych: map, hash_map, Vector-like. Wtedy masz coś w stylu:

template <typename T, typename TContainer>
class Base
{
   // etc.
   protected
   TContainer container ;
}

template <typename Key, typename T>
class DerivedMap     : public Base<T, std::map<Key, T> >      { /* etc. */ }

template <typename Key, typename T>
class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ }

template <typename T>
class DerivedVector  : public Base<T, std::vector<T> >        { /* etc. */ }

Użyłem tego rodzaju kodu niecały miesiąc temu (więc kod jest z pamięci). Po pewnym namyśle uważam, że chociaż generic Base container powinien być klasą abstrakcyjną, nawet jeśli może żyć całkiem dobrze, ponieważ używanie bezpośrednio Base byłoby takim bólem, powinno być zabronione.

Summary Tak więc, masz chronione dane używane przez klasę pochodną. Mimo to, musimy wziąć pod uwagę fakt, że klasa bazowa powinna być abstrakcyjna.

 4
Author: paercebal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-11 21:14:30

W skrócie, tak.

Chronione zmienne członkowskie umożliwiają dostęp do zmiennej z dowolnej podklasy, jak również z dowolnej klasy w tym samym pakiecie. Może to być bardzo przydatne, szczególnie w przypadku danych tylko do odczytu. Nie wierzę, że są one kiedykolwiek konieczne, ponieważ każde użycie chronionej zmiennej członkowskiej może być replikowane przy użyciu prywatnej zmiennej członkowskiej i kilku getterów i setterów.

 3
Author: Jay Stramel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-01 02:25:59

Szczegółowe informacje na temat modyfikatorów dostępu. Net znajdziesz tutaj

Nie ma prawdziwych zalet ani wad chronionych zmiennych członkowskich, jest to pytanie, czego potrzebujesz w konkretnej sytuacji. Ogólnie przyjętą praktyką jest deklarowanie zmiennych członkowskich jako prywatnych i włączanie dostępu zewnętrznego poprzez właściwości. Ponadto niektóre narzędzia (np. niektórzy maperzy O/R) oczekują, że dane obiektów będą reprezentowane przez właściwości i nie rozpoznają publicznych lub chronionych zmiennych składowych. Ale jeśli wiedz, że chcesz, aby Twoje podklasy (i tylko twoje podklasy) miały dostęp do określonej zmiennej, nie ma powodu, aby nie deklarować jej jako chronionej.

 2
Author: Manu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-20 04:41:57

Dla przypomnienia, pod poz. 24 " wyjątkowego C++", w jednym z przypisów Sutter idzie "nigdy nie napiszesz klasy, która ma publiczną lub chronioną zmienną członkowską. prawda? (Niezależnie od słabego przykładu określonego przez niektóre biblioteki.)"

 2
Author: hAcKnRoCk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-15 09:50:35