Pytanie W języku Java różnica między pakietem prywatnym, publicznym, chronionym i prywatnym


W Javie istnieją jasne zasady określające, kiedy należy używać każdego z modyfikatorów dostępu, a mianowicie domyślnego (pakiet prywatny), public, protected i private, podczas robienia class i interface i zajmowanie się dziedziczeniem?


2500
2017-10-18 19:53


pochodzenie


privateukrywa się przed innymi klasami w pakiecie. public wystawia na zajęcia poza pakietem. protected jest wersją public ograniczone tylko do podklas. - Museful
@Tennenrishin - Nie; w przeciwieństwie do C ++, w Javie protected sprawia, że ​​metoda jest również dostępna z całego pakietu. Ta głupota w modelu visiblity Javy przełamuje cel protected. - Nicolas Barbulesco
@Nicolas Jest dostępny z całego pakietu, z lub bez protected. Jako dostęp modyfikator, wszystko to protected ma to wystawiać na podklasy poza pakietem. - Museful
@tennenrishin - cóż, tak powiedział Nicolas ... a ty po prostu to powtarzasz. To, co pierwotnie powiedziałeś, było takie protected - i cytuję - "jest wersją publiczną ograniczoną tylko do podklas", co nie jest prawdą w przypadku twojego własnego dostępu, ponieważ chroniona pozwala również na dostęp przez cały pakiet (ergo, nie ograniczać dostęp do podklas.) - luis.espinal
Zgadzam się również z Nicolasem, że tryb dostępu chronionego w Javie jest idiotyczny. Stało się tak, że Java łączy poziomy (kratkowe) i pionowe ograniczenia dostępu. Domyślnym zakresem jest ograniczenie w poziomie / sieci, przy czym sieć jest pakietem. Publiczne to kolejne ograniczenie horyzontalne, w którym krata jest całym światem. Prywatne i (C ++) są chronione w pionie. Byłoby lepiej, gdybyśmy mieli dostęp do przekroju, powiedzmy, protected-package w rzadkich przypadkach, kiedy naprawdę tego potrzebowaliśmy, odeszliśmy protected być odpowiednikiem wersji chronionej C ++. - luis.espinal


Odpowiedzi:


Oficjalny samouczek może ci się przydać.

            │ Klasa │ Pakiet │ Podklasa │ Podklasa │ Świat
            │ │ │ (ten sam pkg) │ (diff pkg) │
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
publiczne │ + │ + │ + │ + │ +
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
chronione │ + │ + │ + │ + │
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
bez modyfikatora │ + │ + │ + │ │
────────────┼───────┼─────────┼──────────┼──────── ──┼────────
prywatny │ + │ │ │ │

+: dostępne
puste: niedostępne

4660
2017-10-18 19:57



Jeśli próbujesz uzyskać dostęp do chronionej metody lub zmiennej instancji w tej samej klasie, ale na obiekcie, który nie jest tak jak w przypadku .equals (Klass var), czy to działałoby? - Jordan Medlock
Domyślne pola są widoczne w podklasach, jeśli podklasy znajdują się w tym samym pakiecie, co ich klasa nadrzędna. - Maksim Dmitriev
W wersjach Javy i JDK do wersji 1.0.1 można używać prywatnych i chronionych razem, aby stworzyć kolejną formę ochrony, która ograniczyłaby dostęp do metod lub zmiennych wyłącznie do podklas danej klasy. - Vitalii Fedorenko
To dużo głosów za odpowiedź, która nie odpowiada na pytanie, które było gdy powinniśmy używać każdej widoczności (nie jakie są efekty). - Bohemian♦
@Bohemian - odpowiedź zakłada, że ​​wiesz, że powinieneś użyć najmniej dozwolonego specyfikatora dostępu, kiedy tylko jest to możliwe (lub zakłada, że ​​czytasz kompletną odpowiedź, podążając za odnośnikiem, który również daje tę radę). - iheanyi


(Zastrzeżenie: nie jestem programistą Java, jestem programistą Perla, Perl nie ma formalnych zabezpieczeń, być może dlatego tak dobrze rozumiem problem :))

Prywatny

Jakbyś myślał, tylko klasa w którym jest zadeklarowane, może je zobaczyć.

Pakiet prywatny

Mogą być widoczne i używane tylko przez pakiet w którym została zadeklarowana. Jest to ustawienie domyślne w Javie (które niektórzy uważają za błąd).

Chroniony

Pakiet Private + można zobaczyć przez podklasy lub elementy pakietu.

Publiczny

Wszyscy to widzą.

Opublikowany

Widoczny poza kodem, który kontroluję. (Chociaż nie jest to składnia języka Java, jest to ważne dla tej dyskusji).

C ++ definiuje dodatkowy poziom nazywany "przyjacielem", a im mniej o tym wiesz, tym lepiej.

Kiedy należy użyć czego? Cała idea polega na enkapsulacji w celu ukrycia informacji. W miarę możliwości chcesz ukryć szczegóły dotyczące tego, jak coś robią użytkownicy. Czemu? Ponieważ możesz później je zmienić i nie złamać nikomu kodu. Pozwala to optymalizować, refaktoryzować, przeprojektowywać i naprawiać błędy bez obawy, że ktoś użył właśnie tego właśnie poprawionego kodu.

Zasada jest więc taka, aby rzeczy były widoczne tylko tak, jak powinny. Zacznij od prywatnych i zwiększaj tylko widoczność w razie potrzeby. Udostępniaj tylko to, co jest absolutnie niezbędne, aby użytkownik wiedział, każdy szczegół, który powoduje publiczne skurcze, oznacza możliwość przeprojektowania systemu.

Jeśli chcesz, aby użytkownicy mogli dostosowywać zachowania, a nie udostępniać ich wewnętrznym użytkownikom, aby mogli je zastąpić, lepiej jest wpasować je w obiekt i udostępnić go publicznie. W ten sposób mogą po prostu podłączyć nowy obiekt. Na przykład, jeśli pisałeś odtwarzacz CD i chciałeś, aby "go find info about this CD" był konfigurowalny, zamiast upubliczniać te metody, umieściłbyś całą tę funkcję w swoim obiekcie i uczynił tylko obiekt publiczny. . W ten sposób skąpstwo w ujawnianiu twoich wnętrzności zachęca do dobrego składu i oddzielenia obaw

Osobiście trzymam się tylko "prywatnego" i "publicznego". Wiele języków OO właśnie to posiada. "Protected" może być przydatny, ale to naprawdę jest oszustwo. Kiedy interfejs jest bardziej prywatny, nie ma nad nim kontroli i musisz szukać kodów innych ludzi, aby znaleźć zastosowania.

Tutaj pojawia się pomysł "opublikowanego". Zmiana interfejsu (refaktoryzacja go) wymaga znalezienia całego kodu, który z niego korzysta i również to zmienić. Jeśli interfejs jest prywatny, nie ma problemu. Jeśli jest chroniony, musisz znaleźć wszystkie swoje podklasy. Jeśli jest to publiczne, musisz znaleźć cały kod, który używa twojego kodu. Czasem jest to możliwe, na przykład jeśli pracujesz nad kodem firmowym, który jest przeznaczony tylko do użytku wewnętrznego, nie ma znaczenia, czy interfejs jest publiczny. Możesz pobrać cały kod z korporacyjnego repozytorium. Ale jeśli interfejs jest "opublikowany", jeśli jest kod używający go poza twoją kontrolą, to jesteś hosed. Musisz obsługiwać ten interfejs lub ryzykować złamanie kodu. Nawet chronione interfejsy można uznać za opublikowane (dlatego nie zawracam sobie głowy ochroną).

Wiele języków uznaje hierarchiczną naturę public / protected / private za zbyt ograniczającą i niezgodną z rzeczywistością. W tym celu istnieje pojęcie klasa cech, ale to kolejny program.


358
2017-10-18 21:17



przyjaciele -> "Im mniej wiesz o tym, tym lepiej" ---> Zapewnia selektywną widoczność, która jest wciąż lepsza od prywatności paczek. W języku C ++ ma swoje zastosowania, ponieważ nie wszystkie funkcje mogą być funkcjami członkowskimi, a przyjaciele są lepsi od publicznych. Oczywiście istnieje niebezpieczeństwo niewłaściwego użycia przez złe umysły. - Sebastian Mach
Należy również zauważyć, że "chroniony" w C ++ ma inne znaczenie - metoda chroniona jest skutecznie prywatna, ale nadal może być wywołana z klasy dziedziczącej. (W przeciwieństwie do Javy, gdzie może być wywołana przez dowolną klasę w tym samym pakiecie). - Rhys van der Waerden
@RhysvanderWaerden C # jest taki sam jak C ++ w tym aspekcie. Uważam, że to dość dziwne, że Java nie pozwala zadeklarować członka, który jest dostępny dla podklasy, ale nie dla całego pakietu. Jest to do góry nogami - pakiet ma szerszy zakres niż klasa dla dzieci! - Konrad Morawski
@KonradMorawski Pakiet IMHO jest mniejszy niż zakres podklasy. Jeśli nie zadeklarowałeś końcowej klasy, użytkownicy powinni mieć możliwość jej podklasy - więc ochrona java jest częścią twojego opublikowanego interfejsu. OTOH, pakiety są domyślnie tworzone przez jedną organizację: np. com.mycompany.mypackage. Jeśli twój kod deklaruje się w moim pakiecie, niejawnie deklarujesz, że jesteś częścią mojej organizacji, więc powinniśmy się komunikować. Tak więc pakiet publikuje się do mniejszej / łatwiej dostępnej grupy odbiorców (osób w mojej firmie) niż do podklasy (osób, które rozszerzają mój obiekt) i dlatego liczy się jako mniejszą widoczność. - Eponymous
friend jest dobry do definiowania specjalnych relacji między klasami. Pozwala na lepsze hermetyzowanie w wielu przypadkach, gdy jest używane prawidłowo. Na przykład może być użyty przez uprzywilejowaną klasę fabryczną do wstrzyknięcia wewnętrznych zależności do skonstruowanego typu. Ma złą sławę, ponieważ ludzie, którym nie zależy na prawidłowym utrzymaniu dobrze zaprojektowanego modelu obiektu, mogą go nadużywać, aby ułatwić sobie pracę. - Dennis


Oto lepsza wersja tabeli. (Przyszłe dowody z kolumną dla modułów).

Java Access Modifiers

Wyjaśnienia

  • ZA prywatny członek jest tylko dostępne w obrębie tej samej klasy, która jest zadeklarowana.

  • Członek z brak modyfikatora dostępu jest dostępny tylko w ramach klas w tym samym pakiecie.

  • ZA chroniony członek jest dostępny na wszystkich klasach w tym samym pakiecie i w obrębie podklas w innych pakietach.

  • ZA publiczny członek jest dostępny dla wszystkich klas (chyba, że ​​znajduje się w moduł który nie eksportuje pakietu, w którym jest zadeklarowany).


Który modyfikator wybrać?

Modyfikatory dostępu to narzędzie, które pomoże Ci zapobiec przypadkowemu złamaniu enkapsulacji(*). Zadaj sobie pytanie, czy chcesz, aby członek był wewnętrznym elementem klasy, pakietu, hierarchii klas lub w ogóle nie był wewnętrzny, i odpowiednio wybierz poziom dostępu.

Przykłady:

  • Pole long internalCounter prawdopodobnie powinien być prywatny, ponieważ jest zmienny i szczegóły implementacji.
  • Klasa, która powinna być tworzona tylko w klasie fabryki (w tym samym pakiecie) powinna mieć konstruktor z ograniczonym pakietem, ponieważ nie powinno być możliwości wywoływania go bezpośrednio z zewnątrz pakietu.
  • Wewnętrzny void beforeRender() metoda zwana tuż przed renderowaniem i używana jako hak w podklasach powinna być chroniona.
  • ZA void saveGame(File dst) metoda, która jest wywoływana z kodu GUI, powinna być publiczna.

(*) Czym dokładnie jest enkapsulacja?


245
2017-11-10 10:27





                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |   ✘   
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |       ✘       |   ✘   
————————————————+———————————————+———————————+———————————————+———————
private         |              |     ✘     |       ✘       |   ✘    

165
2018-01-09 21:42



Warto umieścić w słowach - "modyfikator chroniony sprawia, że ​​obiekt jest dostępny w innych pakietach, podczas gdy domyślny / bez modyfikatora ogranicza dostęp do tego samego pakietu" - vanguard69
@ vanguard69, the protected modyfikator powoduje zaznaczenie rzecz (klasa, metoda lub pole) dostępne dla jakiejś innej klasy w innym pakiecie tylko iff inna klasa jest podklasą klasy tam, gdzie to protected- oznaczone rzecz jest zadeklarowane. - Abdull
"nonsubbed"? "ta podklasa w innym pakiecie"? Huh. Myślałem, że znam Javę. - sehe
@AlexanderFarber zoptymalizowałeś dla konkretnej konfiguracji przeglądarki? To jest teraz mój chrom a to jest Firefox - sehe
Hmm, przywróćmy wtedy moją zmianę - Alexander Farber


Łatwa reguła. Zacznij od deklarowania wszystkiego jako prywatnego. A następnie postęp w kierunku społeczeństwa, gdy pojawiają się potrzeby i projekt gwarantuje.

Podczas ujawniania członków zadaj sobie pytanie, czy ujawniasz wybory reprezentacyjne lub wybory dotyczące abstrakcji. Pierwszy to coś, czego chcesz uniknąć, ponieważ wprowadzi zbyt wiele zależności od rzeczywistej reprezentacji, a nie jej obserwowalne zachowanie.

Zasadniczo staram się unikać nadpisywania implementacji metod przez ich podklasę; zbyt łatwo zepsuć logikę. Zadeklaruj abstrakcyjne metody chronione, jeśli zamierzasz je zastąpić.

Użyj także adnotacji @Override, gdy nadpisujesz, aby nie doszło do zerwania podczas refaktoryzacji.


131
2017-10-18 20:00



@RuchirBaronia, "world" = cały kod w aplikacji, niezależnie od tego, gdzie jest. - Andrejs


Jest to nieco bardziej skomplikowane niż proste pokazy na siatce. Siatka informuje, czy dostęp jest dozwolony, ale co dokładnie stanowi dostęp? Ponadto poziomy dostępu wchodzą w interakcje z klasami zagnieżdżonymi i dziedziczeniem w złożony sposób.

"Domyślny" dostęp (określony przez brak słowa kluczowego) jest również wywoływany pakiet-prywatny. Wyjątek: w interfejsie żaden modyfikator nie oznacza publicznego dostępu; modyfikatory inne niż publiczne są zabronione. Stałe enum są zawsze publiczne.

Podsumowanie

Czy dozwolony jest dostęp do członka z tym specyfikatorem dostępu?

  • Członek jest private: Tylko jeśli członek jest zdefiniowany w ramach tej samej klasy co kod wywołujący.
  • Członek jest pakietem prywatnym: Tylko jeśli kod wywołujący znajduje się w pakiecie bezpośrednio obejmującym członka.
  • Członek jest protected: Ten sam pakiet lub członek jest zdefiniowany w superklasie klasy zawierającej kod wywołujący.
  • Członek jest public: Tak.

Do czego mają zastosowanie specyfikatory dostępu

Zmienne lokalne i parametry formalne nie mogą przyjmować specyfikatorów dostępu. Ponieważ są one z natury niedostępne na zewnątrz zgodnie z zasadami określania zakresu, są one skutecznie prywatne.

Tylko dla zajęć w górnym zakresie public i pakiet-prywatny są dozwolone. Ten wybór projektu jest prawdopodobnie dlatego, że protected i private byłoby zbędne na poziomie pakietu (nie ma dziedziczenia pakietów).

Wszystkie specyfikatory dostępu są możliwe na elementach klasy (konstruktorach, metodach i statycznych funkcjach składowych, klasach zagnieżdżonych).

Związane z: Dostępność klasy Java

Zamówienie

Specyfikatory dostępu mogą być ściśle uporządkowane

public> protected> package-private> private

to znaczy public zapewnia największy dostęp, private najmniej. Wszelkie odniesienia do członków prywatnych są ważne również dla członka prywatnego pakietu; każde odniesienie do członka prywatnego pakietu jest ważne dla członka chronionego i tak dalej. (Udzielenie dostępu członkom chronionym do innych klas w tym samym pakiecie zostało uznane za błąd).

Uwagi

  • Metody klasy  mogą uzyskać dostęp do prywatnych członków innych obiektów tej samej klasy. Dokładniej, metoda klasy C może uzyskać dostęp do prywatnych członków C na obiektach dowolnej podklasy C. Java nie obsługuje ograniczania dostępu przez instancję, tylko przez klasę. (Porównaj ze Scala, która obsługuje to za pomocą private[this].)
  • Aby zbudować obiekt, potrzebujesz dostępu do konstruktora. Jeśli więc wszystkie konstruktory są prywatne, klasa może być zbudowana tylko przez kod żyjący w klasie (zwykle statyczne metody fabryczne lub inicjatory zmiennych statycznych). Podobnie dla konstruktorów prywatnych lub chronionych pakietami.
    • Tylko posiadanie prywatnych konstruktorów oznacza również, że klasy nie można subklasyzować zewnętrznie, ponieważ Java wymaga, aby konstruktor podklasy domyślnie lub jawnie wywoływał konstruktor nadklasy. (Może jednak zawierać klasę zagnieżdżoną, która ją klasyfikuje).

Klasy wewnętrzne

Musisz także wziąć pod uwagę zagnieżdżony zakresy, takie jak klasy wewnętrzne. Przykładem złożoności jest to, że klasy wewnętrzne mają członków, którzy sami mogą uzyskiwać modyfikatory dostępu. Więc możesz mieć prywatną wewnętrzną klasę z publicznym członkiem; Czy można uzyskać dostęp do członka? (Zobacz poniżej.) Ogólną zasadą jest spojrzenie na zasięg i myślenie rekurencyjne, aby sprawdzić, czy możesz uzyskać dostęp do każdego poziomu.

Jest to jednak dość skomplikowane i dla pełnych szczegółów, sprawdź specyfikację języka Java. (Tak, w przeszłości występowały usterki kompilatora.)

Aby poznać ich interakcje, rozważ ten przykład. Możliwe jest "wyciekanie" prywatnych klas wewnętrznych; zazwyczaj jest to ostrzeżenie:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Dane wyjściowe kompilatora:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Niektóre powiązane pytania:


94
2017-09-13 07:38





Jako zasada:

  • prywatny: zakres klasy.
  • domyślna (lub pakiet-prywatny): zakres pakietu.
  • chroniony: zakres pakietu + dziecko (jak pakiet, ale możemy go podklasować z różnych pakietów). Chroniony modyfikator zawsze utrzymuje relację "rodzic-dziecko".
  • publiczny: wszędzie.

W rezultacie, jeśli podzielimy prawo dostępu na trzy prawa:

  • (Bezpośredni (wywołaj metodę z tej samej klasy).
  • (Odniesienie (wywołaj metodę, używając odwołania do klasy lub przez składnię "kropka").
  • (Dziedzictwo (poprzez podklasę).

wtedy mamy ten prosty stół:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+

63
2017-12-18 18:01





W bardzo krótkim czasie

  • public: dostępne zewsząd.
  • protected: dostępne dla klas tego samego pakietu i podklas znajdujących się w dowolnym pakiecie.
  • default (bez określonego modyfikatora): dostępny dla klas tego samego pakietu.
  • private: dostępne tylko w tej samej klasie.

43
2017-10-27 17:49





Najbardziej niezrozumianym modyfikatorem dostępu w Javie jest protected. Wiemy, że jest podobny do domyślnego modyfikatora z jednym wyjątkiem, w którym podklasy mogą go zobaczyć. Ale jak? Oto przykład, który miejmy nadzieję wyjaśnia zamieszanie:

  • Załóżmy, że mamy 2 klasy; Father i Sonkażdy w swoim pakiecie:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
  • Dodajmy chronioną metodę foo() do Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
    
  • Metoda foo() można wywoływać w 4 kontekstach:

    1. Wewnątrz klasy, która znajduje się w tym samym pakiecie, gdzie foo() definiuje (fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
      
    2. Wewnątrz podklasy, na bieżącej instancji za pośrednictwem this lub super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
      
    3. Na referencji, której typem jest ta sama klasa:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
      
    4. Na odwołanie, którego typ jest klasa nadrzędna i jest wewnątrz pakiet gdzie foo() definiuje (fatherpackage) [To może być zawarte w kontekście nr. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
      
  • Następujące sytuacje są nieprawidłowe.

    1. Na odwołanie, którego typ jest klasa nadrzędna i jest na zewnątrz pakiet gdzie foo() definiuje (fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
      
    2. Nie-podklasa wewnątrz pakietu podklasy (podklasa A dziedziczy chronione elementy przed swoim rodzicem i czyni je prywatnymi dla nie-podklas):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
      

32
2017-11-15 20:06



Object#clone() jest przykładem a protected członek. - Eng.Fouad
Jaka jest różnica między robieniem super.foo() i pierwsza nieważna sytuacja f.foo()? - cst1992
@ cst1992 Jest to mylące, ale patrz Specyfikacja Języka Java 6.6.2: "Dostęp do chronionego elementu lub konstruktora obiektu może być uzyskiwany spoza pakietu, w którym jest on zadeklarowany tylko przez kod, który jest odpowiedzialny za implementację tego obiektu". Z super.foo () odniesienie "super" jest "bezpośrednio odpowiedzialne za implementację", ale odwołanie "f" nie jest. Czemu? Ponieważ możesz być w 100% pewny, że "super" jest typu Ojca, ale nie dla "f"; w czasie wykonywania mógłby to być inny podtyp Ojca. Widzieć docs.oracle.com/javase/specs/jls/se9/html/... - skomisa
Odświeżanie czyta odpowiedź od kogoś, kto rozumie protected. Niestety, wszystkie inne odpowiedzi na tej stronie, które definiują protected trochę źle. - Dawood ibn Kareem