JavaRush /Blog Java /Random-PL /Modyfikatory dostępu. Prywatne, chronione, domyślne, publ...

Modyfikatory dostępu. Prywatne, chronione, domyślne, publiczne

Opublikowano w grupie Random-PL
Cześć! Na dzisiejszym wykładzie zapoznamy się z pojęciem „ modyfikatorów dostępu ” i przyjrzymy się przykładom pracy z nimi. Modyfikatory dostępu.  Prywatny, chroniony, domyślny, publiczny - 1Chociaż słowo „poznajmy się” nie będzie do końca trafne: większość z nich znacie już z poprzednich wykładów. Na wszelki wypadek odświeżmy pamięć o najważniejszej sprawie. Modyfikatory dostępu to najczęściej słowa kluczowe, które regulują poziom dostępu do różnych części Twojego kodu. Dlaczego „najczęściej”? Ponieważ jeden z nich jest ustawiony domyślnie i nie jest oznaczony słowem kluczowym :) W Javie są w sumie cztery modyfikatory dostępu. Podajemy je w kolejności od najbardziej rygorystycznej do najbardziej „miękkiej”:
  • prywatny;
  • chroniony;
  • domyślny (pakiet widoczny);
  • publiczny.
Przyjrzyjmy się każdemu z nich, zdecydujmy, kiedy mogą nam się przydać i podajmy przykłady :)

Modyfikator prywatny

Modyfikatory dostępu.  Prywatny, chroniony, domyślny, publiczny - 2Private— najbardziej restrykcyjny modyfikator dostępu. Ogranicza widoczność danych i metod w ramach jednej klasy. Znasz ten modyfikator z wykładu o getterach i setterach. Czy pamiętasz ten przykład?
public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Miauczeć!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Pisaliśmy już o tym w jednym z artykułów wcześniej. Tutaj popełniliśmy poważny błąd: otworzyliśmy nasze dane, w wyniku czego koledzy programiści mieli bezpośredni dostęp do pól klas i zmianę ich wartości. Co więcej, wartości te zostały przypisane bez kontroli, dzięki czemu w naszym programie możliwe jest stworzenie kota w wieku -1000 lat, o imieniu „” i wadze 0. Aby rozwiązać ten problem, możemy używane metody pobierające i ustawiające , a także ograniczony dostęp do danych za pomocą modyfikatora private.
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Miauczeć!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // sprawdzenie parametru wejściowego
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // sprawdzenie parametru wejściowego
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // sprawdzenie parametru wejściowego
       this.weight = weight;
   }
}
Właściwie ograniczenie dostępu do pól i wdrożenie modułów pobierających-setujących jest najczęstszym przykładem użycia privatew prawdziwej pracy. Oznacza to, że głównym celem tego modyfikatora jest implementacja enkapsulacji w programie. Nawiasem mówiąc, dotyczy to nie tylko pól. Wyobraź sobie, że w Twoim programie znajduje się metoda implementująca BARDZO złożoną funkcjonalność. Oto przykład... Załóżmy, że Twoja metoda readDataFromCollider()pobiera adres z danymi jako dane wejściowe, odczytuje dane z Wielkiego Zderzacza Hadronów w formacie bajtowym, konwertuje te dane na tekst, zapisuje je do pliku i drukuje. Już sam opis metody wygląda przerażająco, a co dopiero kod :) Aby zwiększyć czytelność kodu dobrze byłoby nie pisać złożonej logiki metody w jednym miejscu, a wręcz przeciwnie, zepsuć funkcjonalność na osobne metody. Metoda readByteData()odpowiada np. za odczyt danych, convertBytesToSymbols()konwersję danych odczytanych ze zderzacza na tekst, saveToFile()zapisanie powstałego tekstu do pliku i printColliderData()wydrukowanie naszego pliku z danymi. Metoda readDataFromCollider()byłaby znacznie prostsza:
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // odczytuje dane w bajtach
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // konwertuje bajty na znaki
   }

   public File saveToFile(String[] colliderData) {

       // zapisz odczytane dane do pliku
   }

   public void printColliderData(File fileWithColliderData) {

       // wydrukuj dane z pliku
   }
}
Jak jednak pamiętacie z wykładu o interfejsach, użytkownik otrzymuje dostęp jedynie do finalnego interfejsu. Nasze 4 metody nie są tego częścią. Są pomocnicze : stworzyliśmy je, aby poprawić czytelność kodu i uniknąć wtłaczania czterech różnych zadań w jedną metodę. Nie ma potrzeby udostępniania użytkownikowi tych metod. Jeśli użytkownik ma dostęp do metody podczas pracy ze zderzaczem convertBytesToSymbols(), najprawdopodobniej po prostu nie zrozumie, czym jest ta metoda i dlaczego jest potrzebna. Jakie bajty są konwertowane? Skąd oni przyszli? Po co konwertować je na tekst? Logika działająca w tej metodzie nie jest częścią interfejsu użytkownika. Tylko metoda readDataFromCollider()jest częścią interfejsu. Co zrobić z tymi czterema „wewnętrznymi” metodami? Prawidłowy! Ogranicz dostęp do nich za pomocą modyfikatora private. W ten sposób mogą łatwo wykonywać swoją pracę wewnątrz klasy i nie dezorientować użytkownika, który nie potrzebuje logiki każdego z nich z osobna.
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // odczytuje dane w bajtach
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // konwertuje bajty na znaki
   }

   private File saveToFile(String[] colliderData) {
       // zapisz odczytane dane do pliku
   }

   private void printColliderData(File fileWithColliderData) {
       // wydrukuj dane z pliku
   }
}

Modyfikator chroniony

Następnym najbardziej restrykcyjnym modyfikatorem dostępu jest protected. Widoczne będą Modyfikatory dostępu.  Prywatny, chroniony, domyślny, publiczny - 3 pola i metody oznaczone modyfikatorem dostępu :protected
  • we wszystkich klasach znajdujących się w tym samym pakiecie co nasz;
  • we wszystkich klasach następczych po naszej klasie.
Od razu trudno sobie wyobrazić, kiedy może to być potrzebne. Nie zdziw się: protectedprzypadków zastosowania jest znacznie mniej niż private, a są one specyficzne. Wyobraźmy sobie, że mamy klasę abstrakcyjną AbstractSecretAgentoznaczającą tajnego agenta jakiejś agencji wywiadowczej, a także pakiet top_secretzawierający tę klasę i jej potomków. Klasy konkretne - FBISecretAgent, MI6SecretAgent, MossadSecretAgentitp. - są z niego dziedziczone. Wewnątrz klasy abstrakcyjnej chcemy zaimplementować licznik agentów. Kiedy w programie zostanie utworzony nowy obiekt agenta, jego liczba wzrośnie.
package top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Ale nasi agenci są tajni! Oznacza to, że tylko oni i nikt inny nie powinien wiedzieć o ich numerze. Możemy łatwo dodać modyfikator protecteddo pola agentCounti wówczas albo obiekty innych klas tajnych agentów, albo te klasy, które znajdują się w naszym „tajnym” pakiecie, mogą uzyskać swoją wartość top_secret.
public abstract class AbstractSecretAgent {

   protected static int agentCount = 0;
}
Właśnie do tak konkretnych zadań potrzebny jest modyfikator protected:)

modyfikator widoczny w pakiecie

Następny na naszej liście jest modyfikator defaultlub, jak to się nazywa, package visible. Nie jest to oznaczone słowem kluczowym, ponieważ jest ono domyślnie ustawione w Javie dla wszystkich pól i metod. Jeśli napiszesz w swoim kodzie -
int x = 10;
... zmienna xbędzie miała taki sam package visibledostęp. Jeśli metoda (lub zmienna) nie jest oznaczona żadnym modyfikatorem, uważa się, że jest oznaczona „modyfikatorem domyślnym”. Zmienne lub metody z takim modyfikatorem (czyli w ogóle bez niego) są widoczne dla wszystkich klas pakietu, w którym są zadeklarowane. I tylko do nich. Jego zastosowanie jest ograniczone, podobnie jak modyfikatora protected. Najczęściej defaultopcja -access jest używana w pakiecie, w którym istnieją klasy narzędziowe, które nie implementują funkcjonalności wszystkich innych klas w tym pakiecie. Podajmy przykład. Wyobraź sobie, że mamy pakiet „ usług ”. Wewnątrz znajdują się różne klasy współpracujące z bazą danych. Przykładowo istnieje klasa UserServiceodczytująca dane użytkownika z bazy danych, klasa CarServiceczytająca dane o samochodach z tej samej bazy danych oraz inne klasy, z których każda pracuje z własnym typem obiektów i odczytuje dane o nich z bazy danych.
package services;

public class UserService {
}

package services;

public class CarService {
}
Jednak łatwo może dojść do sytuacji, gdy dane w bazie danych są w jednym formacie, a my potrzebujemy ich w innym. Wyobraź sobie, że data urodzenia użytkownika w bazie danych jest przechowywana w formacie TIMESTAMP ZE STREFĄ CZASOWĄ...
2014-04-04 20:32:59.390583+02
...zamiast tego potrzebujemy najprostszego obiektu - java.util.Date. W tym celu możemy stworzyć wewnątrz pakietu servicesspecjalną klasę Mapper. Będzie odpowiedzialny za konwersję danych z bazy danych na znane nam obiekty Java. Prosta klasa pomocnicza. Zwykle tworzymy wszystkie klasy jako public class ClassName, ale nie jest to konieczne. Możemy zadeklarować naszą klasę pomocniczą po prostu jako class Mapper. W tym przypadku nadal spełnia swoje zadanie, ale nie jest widoczny dla nikogo poza pakietem services!
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
I to jest w istocie poprawna logika: dlaczego ktoś spoza pakietu miałby widzieć klasę pomocniczą, która działa tylko z klasami z tego samego pakietu?

modyfikator publiczny

I ostatni na liście, ale nie mniej ważny - modyfikator public! Poznałeś go pierwszego dnia studiów w JavaRush, uruchamiając public static void main(String[] args). Modyfikatory dostępu.  Prywatne, chronione, domyślne, publiczne - 4 Teraz, gdy przestudiowałeś wykłady o interfejsach, jego cel jest dla ciebie oczywisty :) W końcu publiczostał stworzony, aby dać coś użytkownikom. Na przykład interfejs twojego programu. Załóżmy, że napisałeś program tłumaczący, który może przetłumaczyć tekst rosyjski na angielski. Utworzyłeś metodę translate(String textInRussian), w ramach której zaimplementowana jest niezbędna logika. Oznaczyłeś tę metodę słowem publici teraz stanie się ona częścią interfejsu:
public class Translator {

   public String translate(String textInRussian) {

       // tłumaczy tekst z rosyjskiego na angielski
   }
}
Wywołanie tej metody możesz powiązać z przyciskiem „tłumacz” na ekranie programu – i gotowe! Każdy może z niego skorzystać. Części kodu oznaczone modyfikatorem publicprzeznaczone są dla użytkownika końcowego. Dla przykładu z życia privatesą to wszystkie procesy zachodzące wewnątrz telewizora podczas jego pracy i publicsą to przyciski na pilocie telewizora, za pomocą których użytkownik może nim sterować. Jednocześnie nie musi wiedzieć, jak działa telewizor i jak działa. Pilot zdalnego sterowania to zestaw publicmetod: on(), off(), nextChannel(), previousChannel(), increaseVolume(), decreaseVolume()itp.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION