CodeGym/Blog Java/Random-PL/Modyfikatory dostępu w Javie
Autor
Artem Divertitto
Senior Android Developer at United Tech

Modyfikatory dostępu w Javie

Opublikowano w grupie Random-PL
Cześć! W dzisiejszej lekcji zapoznamy się z koncepcją modyfikatorów dostępu i rozważymy przykłady, jak z nimi pracować. Oczywiście powiedzenie „zapoznaj się” nie jest do końca trafne: większość z nich znasz już z poprzednich lekcji. Na wszelki wypadek odświeżmy sobie pamięć o najważniejszym punkcie. Dostęp do modyfikatorów to najczęściej słowa kluczowe regulujące dostęp do różnych części kodu. Dlaczego „najczęściej”? Ponieważ jeden z nich jest domyślnie ustawiony bez użycia słowa kluczowego :) Java ma cztery modyfikatory dostępu. Wymieniamy je w kolejności od najbardziej restrykcyjnej do najbardziej „pobłażliwej”:
  • prywatny;
  • domyślny (pakiet widoczny);
  • chroniony;
  • publiczny.
Przyjrzyjmy się każdemu z nich i określmy, kiedy mogą być przydatne. I podamy przykłady :)

Prywatny modyfikator

Modyfikatory dostępu.  Prywatny, chroniony, domyślny, publiczny — 2private jest najbardziej restrykcyjnym modyfikatorem dostępu. Ogranicza widoczność danych i metod do jednej klasy. Ten modyfikator znasz z lekcji o getterach i setterach. 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("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Rozważaliśmy to na poprzedniej lekcji. Popełniliśmy tutaj poważny błąd: upubliczniliśmy nasze dane, co umożliwiło innym programistom bezpośredni dostęp do pól i zmianę ich wartości. Co więcej... wartości te zostały nadane bez żadnych kontroli. Oznacza to, że nasz program mógłby stworzyć kota o nazwie „” w wieku -1000 lat i wadze 0. Aby rozwiązać ten problem, użyliśmy getterów i setterów, a także użyliśmy modyfikatora private, aby ograniczyć dostęp do danych.
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("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // input parameter check
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // input parameter check
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // input parameter check
       this.weight = weight;
   }
}
Zasadniczo ograniczanie dostępu do pól i wdrażanie metod pobierających i ustawiających to najczęstsze przykłady tego, jak prywatneprzydałby się w prawdziwej pracy. Innymi słowy, głównym celem tego modyfikatora jest osiągnięcie enkapsulacji w programie. Nawiasem mówiąc, dotyczy to nie tylko pól. Wyobraź sobie, że w twoim programie jest metoda, która implementuje BARDZO złożoną funkcjonalność. Co możemy zasugerować jako przykład? Załóżmy, że twoja metoda readDataFromCollider() przyjmuje jako dane wejściowe adres danych, 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, nie mówiąc już o kodzie :) Aby kod był bardziej czytelny, lepiej nie pisać całej złożonej logiki metody w jednym miejscu. Zamiast tego powinniśmy podzielić funkcjonalność na osobne metody. Na przykład readByteData()odpowiada za odczyt danych, metoda convertBytesToSymbols() konwertuje dane odczytane z collidera na tekst, metoda saveToFile() zapisuje otrzymany tekst do pliku, a metoda printColliderData() drukuje nasz plik danych. Ostatecznie nasza metoda readDataFromCollider() będzie 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) {

       // Reads data in bytes
   }

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

       // Converts bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // Saves read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // Prints data from the file
   }
}
Jednak, jak zapewne pamiętasz z lekcji o interfejsach, użytkownik uzyskuje dostęp tylko do zewnętrznego interfejsu. A nasze 4 metody nie są tego częścią. Są to metody pomocnicze: stworzyliśmy je, aby poprawić czytelność kodu i nie upychać czterech różnych zadań w jednej metodzie. Nie musisz udzielać użytkownikowi dostępu do tych metod. Jeśli użytkownicy mają dostęp do metody convertBytesToSymbols() podczas pracy ze zderzaczem, najprawdopodobniej będą po prostu zdezorientowani tą metodą i będą się zastanawiać, do czego ona służy. Jakie bajty są konwertowane? Skąd oni przyszli? Po co konwertować je na tekst? Logika wykonywana w tej metodzie nie jest częścią interfejsu udostępnianego użytkownikowi. Tylko readDataFromCollider()Metoda jest częścią interfejsu. Co więc robimy z tymi czterema „wewnętrznymi” metodami? Prawidłowy! Użyj modyfikatora private , aby ograniczyć do nich dostęp. Dzięki temu mogą spokojnie wykonywać swoją pracę w klasie bez dezorientowania użytkownika, który nie musi znać logiki każdej metody.
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) {
       // Reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // Converts bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // Saves read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // Prints data from the file
   }
}

Chroniony modyfikator

Kolejnym najbardziej restrykcyjnym modyfikatorem jest chroniony . Modyfikatory dostępu.  Prywatny, chroniony, domyślny, publiczny — 3Pola i metody oznaczone chronionym modyfikatorem dostępu będą widoczne:
  • we wszystkich klasach objętych tym samym pakietem co nasz;
  • we wszystkich klasach, które dziedziczą naszą klasę.
Na początku trudno sobie wyobrazić, kiedy może to być potrzebne. Nie zdziw się: istnieje znacznie mniej przypadków użycia protected niż private i są one bardzo specyficzne. Wyobraźmy sobie, że mamy abstrakcyjną klasę AbstractSecretAgent , która reprezentuje tajnego agenta w jakiejś służbie wywiadowczej, a także pakiet top_secret , który zawiera tę klasę i jej potomków. Konkretne klasy, takie jak FBISecretAgent , MI6SecretAgent , MossadSecretAgent itp. Dziedziczą to. Wewnątrz klasy abstrakcyjnej chcemy zaimplementować licznik agentów. Zwiększy się, gdy gdzieś w programie zostanie utworzony nowy agent. pakiet top_secret;
public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Ale nasi agenci są tajni! Oznacza to, że oni i nikt inny nie powinien wiedzieć, ile ich istnieje. Możemy łatwo dodać chroniony modyfikator do pola agent_counter . Wtedy instancje innych tajnych klas agentów i inne klasy znajdujące się w naszym pakiecie top_secret mogą uzyskać jego wartość.
public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
I to jest rodzaj specjalistycznego zadania, które wymaga chronionego modyfikatora :)

Widoczny modyfikator pakietu

Następny na liście jest domyślny modyfikator, znany również jako widoczny modyfikator pakietu. Nie jest wskazywane przez słowo kluczowe, ponieważ Java stosuje je domyślnie do wszystkich pól i metod. Jeśli napiszesz w swoim kodzie:
int x = 10
zmienna x będzie miała widoczny dostęp do tego pakietu. Łatwo zapamiętać, co robi. Zasadniczo domyślnie = chronione dziedziczenie :) Podobnie jak chroniony modyfikator, jego zastosowanie jest ograniczone. Najczęściej dostęp domyślny jest używany w pakiecie, który ma pewne klasy narzędzi, które nie implementują funkcjonalności wszystkich innych klas w pakiecie. Podajmy przykład. Wyobraź sobie, że mamy pakiet „usług”. Zawiera różne klasy, które współpracują z bazą danych. Na przykład istnieje klasa UserService , która odczytuje dane użytkownika z bazy danych, CarServiceklasa, która odczytuje dane samochodu z tej samej bazy danych, oraz inne klasy, z których każda współpracuje z określonymi typami obiektów i odczytuje odpowiednie dane z bazy danych.
package services;

public class UserService {
}

package services;

public class CarService {
}
Ale byłoby łatwo, gdyby dane w bazie danych były w jednym formacie, a my potrzebujemy ich w innym. Wyobraź sobie, że daty urodzenia użytkowników w bazie danych są przechowywane jako <TIMESTAMP WITH TIME ZONE>...
2014-04-04 20:32:59.390583+02
... a zamiast tego potrzebujemy najprostszego obiektu — java.util.Date . Aby rozwiązać ten problem, w pakiecie usług możemy stworzyć specjalną klasę Mapper . Będzie odpowiedzialny za konwersję danych z bazy danych do znanych nam obiektów Javy. Prosta klasa pomocnicza. Zwykle deklarujemy wszystkie klasy jako public class ClassName , ale nie jest to wymagane. 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 usług !
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
A oto podstawowe rozumowanie: dlaczego ktoś spoza pakietu miałby widzieć klasę pomocniczą, która działa tylko z klasami w tym pakiecie?

Modyfikator publiczny

I wreszcie modyfikator publiczny ! Spotkałeś ten modyfikator pierwszego dnia nauki w CodeGym, kiedy po raz pierwszy uruchomiłeś public static void main(String[] args) . Modyfikatory dostępu.  Prywatny, chroniony, domyślny, publiczny — 4Teraz, kiedy przestudiowałeś lekcję o interfejsach, jej cel jest dla ciebie oczywisty :) W końcu modyfikator public został 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 tłumaczyć rosyjski tekst na angielski. Utworzyłeś metodę translate(String textInRussian) , która implementuje całą niezbędną logikę. Oznaczyłeś tę metodę słowem public , a teraz jest częścią interfejsu:
public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
Możesz powiązać tę metodę z przyciskiem „Tłumacz” na ekranie i gotowe! Każdy może z niego korzystać. Części kodu oznaczone modyfikatorem public są przeznaczone dla użytkownika końcowego. Podając rzeczywisty przykład, prywatny dotyczy wszystkich procesów zachodzących w telewizorze, ale publiczny dotyczy przycisków na pilocie służącym do zarządzania telewizorem. Co więcej, użytkownik nie musi wiedzieć, jak zbudowany jest telewizor ani jak działa. Pilot zdalnego sterowania to zestaw publicznych metod: on() , off() , nextChannel() , previousChannel() , gainVolume() , reduceVolume() itd. Aby utrwalić to, czego się nauczyłeś, zalecamy obejrzenie lekcji wideo z naszego kursu języka Java
Komentarze
  • Popularne
  • Najnowsze
  • Najstarsze
Musisz się zalogować, aby dodać komentarz
Ta strona nie ma jeszcze żadnych komentarzy