CodeGym /Java блог /Случаен /Модификатори на достъп в Java
John Squirrels
Ниво
San Francisco

Модификатори на достъп в Java

Публикувано в групата
здрасти В днешния урок ще се запознаем с концепцията за модификатори на достъп и ще разгледаме примери How да работим с тях. Разбира се, да кажете „запознайте се“ не е съвсем правилно: вече сте запознати с повечето от тях от предишни уроци. За всеки случай нека опресним паметта си за най-важното. Модификаторите за достъп най-често са ключови думи, които регулират достъпа до различни части от вашия code. Защо "най-често"? Тъй като един от тях е зададен по подразбиране без използване на ключова дума :) Java има четири модификатора за достъп. Изброяваме ги в ред от най-рестриктивните до най-снизходителните:
  • частни;
  • по подразбиране (пакетът е видим);
  • защитени;
  • публичен.
Нека да разгледаме всеки от тях и да определим кога могат да бъдат полезни. И ще дадем примери :)

Частният модификатор

Модификатори за достъп.  Частен, защитен, по подразбиране, публичен - 2private е най-рестриктивният модификатор за достъп. Той ограничава видимостта на данните и методите в рамките на един клас. Познавате този модификатор от урока за гетери и сетери. Помните ли този пример?

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;
   }
}
Разгледахме го в предишен урок. Тук допуснахме сериозна грешка: правим данните си публични, което позволи на колегите програмисти да имат директен достъп до полетата и да променят стойностите им. Нещо повече... тези стойности са присвоени без ниHowви проверки. Това означава, че нашата програма може да създаде котка на име "" с възраст -1000 години и тегло 0. За да разрешим този проблем, използвахме гетери и сетери, а също така използвахме частния модификатор, за да ограничим достъпа до данните.

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;
   }
}
По принцип ограничаването на достъпа до полета и внедряването на гетери и сетери са най-честите примери за това колко поверителни саще се използва в реална работа. С други думи, основната цел на този модификатор е да постигне капсулиране в програма. Между другото, това не се отнася само за полета. Представете си, че във вашата програма има метод, който реализира някои МНОГО сложни функции. Какво можем да предложим като пример? Да приемем, че вашият метод readDataFromCollider() приема като вход address на данни, чете данни от Големия адронен колайдер в byteов формат, преобразува тези данни в текст, записва ги във файл и ги отпечатва. Дори описанието на метода изглежда плашещо, да не говорим за codeа :) За да направите codeа по-четлив, би било най-добре да не записвате цялата сложна логика на метода на едно място. Вместо това трябва да разделим функционалността на отделни методи. Например readByteData()отговаря за четенето на данни, методът convertBytesToSymbols() преобразува данните, прочетени от колайдера в текст, методът saveToFile() записва получения текст във файл, а методът printColliderData() отпечатва нашия файл с данни. В крайна сметка нашият метод readDataFromCollider() ще бъде много по-прост:

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
   }
}
Въпреки това, Howто ще си спомните от урока за интерфейсите, потребителят получава достъп само до външния интерфейс. И нашите 4 метода не са част от него. Те са помощни методи: създадохме ги, за да подобрим четливостта на codeа и да не натъпкваме четири различни задачи в един метод. Не е необходимо да давате на потребителя достъп до тези методи. Ако потребителите имат достъп до метода convertBytesToSymbols() , когато работят с колайдера, те най-вероятно просто ще бъдат объркани от метода и ще се чудят за Howво служи. Какви byteове се преобразуват? Откъде са дошли? Защо да ги конвертирате в текст? Логиката, изпълнявана в този метод, не е част от интерфейса, изложен на потребителя. Само readDataFromCollider()методът е част от интерфейса. И така, Howво правим с тези четири „вътрешни“ метода? вярно! Използвайте частния модификатор, за да ограничите достъпа до тях. Това им позволява спокойно да изпълняват работата си в класа, без да объркват потребителя, който не трябва да знае логиката на всеки отделен метод.

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
   }
}

Защитеният модификатор

Следващият най-рестриктивен модификатор е protected . Модификатори за достъп.  Частен, защитен, по подразбиране, публичен - 3Полетата и методите, маркирани от модификатора за защитен достъп, ще бъдат видими:
  • във всички класове, включени в същия пакет като нашия;
  • във всички класове, които наследяват нашия клас.
В началото е трудно да си представим кога това може да е необходимо. Не се изненадвайте: има много по-малко случаи на употреба за protected отколкото за private и те са много специфични. Представете си, че имаме абстрактен клас AbstractSecretAgent , който представлява таен агент в няHowва разузнавателна служба, Howто и пакет top_secret , който съдържа този клас и неговите наследници. Конкретни класове като FBISecretAgent , MI6SecretAgent , MossadSecretAgent и др. го наследяват. Вътре в абстрактния клас искаме да внедрим брояч на агенти. Ще се увеличи, когато някъде в програмата бъде създаден нов агент. пакет top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Но нашите агенти са тайни! Това означава, че те и никой друг не трябва да знаят колко от тях съществуват. Можем лесно да добавим модификатора protected към полето agent_counter . Тогава екземпляри на други класове на таен агент и други класове, намиращи се в нашия пакет top_secret , могат да получат неговата стойност.

public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
И това е вид специализирана задача, която изисква защитен модификатор :)

Видимият модификатор на пакета

Следващият в списъка е модификаторът по подразбиране , известен също като видим модификатор на пакета. Не се обозначава с ключова дума, тъй като Java го прилага по подразбиране към всички полета и методи. Ако напишете следното във вашия code:

int x = 10
променливата x ще има видим достъп до този пакет. Лесно е да запомните Howво прави. По принцип по подразбиране = защитено наследяване :) Подобно на защитения модификатор, приложението му е ограничено. Най-често достъпът по подразбиране се използва в пакет, който има някои помощни класове, които не изпълняват функционалността на всички останали класове в пакета. Да дадем пример. Представете си, че имаме пакет „услуги“. Съдържа различни класове, които работят с база данни. Например, има клас UserService , който чете потребителски данни от базата данни, CarServiceклас, който чете данни за автомобor от същата база данни, и други класове, всеки от които работи с конкретни типове обекти и чете съответните данни от базата данни.

package services;

public class UserService {
}

package services;

public class CarService {
}
Но би било лесно данните в базата данни да са в един формат, а да ни трябват в друг. Представете си, че рождените дати на потребителите в базата данни се съхраняват като <TIMESTAMP WITH TIME ZONE>...

2014-04-04 20:32:59.390583+02
...и instead of това се нуждаем от най-простия обект — java.util.Date . За да разрешим този проблем, вътре в пакета услуги можем да създадем специален клас Mapper . Той ще отговаря за преобразуването на данни от базата данни в познатите ни Java обекти. Прост помощен клас. Обикновено декларираме всички класове като публичен клас ClassName , но това не е изискване. Можем да декларираме нашия помощен клас просто като class Mapper . В този случай той все още върши работата си, но не е видим за никого извън пакета услуги !

package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
И ето основното разсъждение: защо някой извън пакет трябва да вижда помощен клас, който работи само с класовете в този пакет?

Общественият модификатор

И не на последно място публичният модификатор! Срещнахте този модификатор в първия си ден на обучение в CodeGym, когато за първи път стартирахте public static void main(String[] args) . Модификатори за достъп.  Частен, защитен, по подразбиране, публичен - 4Сега, след като изучихте урока за интерфейсите, целта му е очевидна за вас :) В крайна сметка публичният модификатор е създаден, за да даде нещо на потребителите. Например интерфейсът на вашата програма. Да предположим, че сте написали програма за превод, която може да превежда руски текст на английски. Създадохте метод translate(String textInRussian) , който прилага цялата необходима логика. Маркирахте този метод с думата public и сега той е част от интерфейса:

public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
Можете да свържете този метод с бутона „Превод“ на екрана и сте готови! Всеки може да го използва. Частите от codeа, маркирани с публичен модификатор, са предназначени за крайния потребител. Предоставяйки пример от реалния живот, private е за всички процеси, които се случват в телевизора, но public е за бутоните на дистанционното управление, използвани за управление на телевизора. Нещо повече, потребителят не трябва да знае How е изграден телевизорът or How работи. Дистанционното управление е набор от публични -методи: on() , off() , nextChannel() , previousChannel() , increaseVolume() , reduceVolume() и т.н. За да затвърдите наученото, ви предлагаме да гледате видео урок от нашия курс по Java
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION