Модификаторы доступа и инкапсуляция
Все члены класса в языке Java - поля и методы, свойства - имеют модификаторы доступа. В
прошлых темах мы уже сталкивались с модификатором public. Модификаторы доступа
позволяют задать допустимую область видимости для членов класса, то есть контекст, в котором
можно употреблять данную переменную или метод.
В Java используются следующие модификаторы доступа:
public: публичный, общедоступный класс или член класса. Поля и методы, объявленные с
модификатором public, видны другим классам из текущего пакета и из внешних пакетов.
private: закрытый класс или член класса, противоположность модификатору public.
Закрытый класс или член класса доступен только из кода в том же классе.
protected: такой класс или член класса доступен из любого места в текущем классе или
пакете или в производных классах, даже если они находятся в других пакетах
Модификатор по умолчанию. Отсутствие модификатора у поля или метода класса
предполагает применение к нему модификатора по умолчанию. Такие поля или методы видны
всем классам в текущем пакете.
Рассмотрим все возможные случаи. Допустим, у нас есть проект со следующей структурой:
В данном случае имеется три пакета. Пакет incapsulation содержит главный класс
программы, в котором и прописан метод main. Его мы трогать не будем.
И также определены два пакета incapsulation.package1, который содержит классы ClassA и
ClassB, и пакет incapsulation.package2, который содержит классы ClassC и ClassD.
Класс ClassA содержит весь возможный набор модификаторов доступа:
package incapsulation.package1;
public class ClassA {
private int num1=3;
int num2 = 2;
protected int num3 =3;
public int num4=4;
public void displayNum1(){
System.out.println(num1);
}
protected void displayNum2(){
System.out.println(num2);
}
void displayNum3(){
System.out.println(num3);
}
private void displayNum4(){
System.out.println(num4);
}
}
Модификатор доступа должен предшествовать остальной часть определения переменной
или метода.
Пусть класс ClassB использует ClassA:
package incapsulation.package1;
public class ClassB {
public void result(){
ClassA classA = new ClassA();
//System.out.println(classA.num1); // ошибка, так как num1 - private
classA.displayNum1(); // public
System.out.println(classA.num2); // идентификатор по умолчанию
classA.displayNum2(); // protected
System.out.println(classA.num3); // protected
classA.displayNum3(); // идентификатор по умолчанию
System.out.println(classA.num4); // public
//classA.displayNum4(); // ошибка, так как displayNum4() - private
}
}
Так как классы ClassB и ClassA находятся в одном пакете, то мы сможем использовать все
поля и методы класса ClassA в ClassB кроме тех, что объявлены как private.
Теперь используем класс ClassA в классе ClassC:
package incapsulation.package2;
import incapsulation.package1.ClassA;
public class ClassC{
public void result(){
ClassA classA = new ClassA();
//System.out.println(classA.num1); // ошибка, так как num1 - private
classA.displayNum1(); // public
//System.out.println(classA.num2); // ошибка, так как num2 - идентификатор
по умолчанию
//classA.displayNum2(); //ошибка, так как доступ - protected
//System.out.println(classA.num3); // ошибка, так как доступ - protected
//classA.displayNum3(); //ошибка, так как доступ - идентификатор по
умолчанию
System.out.println(classA.num4); // public
//classA.displayNum4(); // ошибка, так как displayNum4() - private
}
}
Так как класс ClassC находится в другом пакете и не является наследником класса ClassA, то
в нем можно использовать только те поля и методы класса ClassA, которые объявлены с
модификатором public.
И последний случай - ClassD является наследником класса ClassA, но находится в другом
пакете (чуть позже мы более подробно разберем наследование):
package incapsulation.package2;
import incapsulation.package1.ClassA;
public class ClassD extends ClassA {
public void result(){
//System.out.println(num1); // ошибка, так как num1 - private
displayNum1(); // public
//System.out.println(num2); // ошибка, так как доступ - идентификатор по
умолчанию
displayNum2(); // protected
System.out.println(num3); // protected
//displayNum3(); //ошибка, так как доступ по умолчанию
System.out.println(num4); // public
//classA.displayNum4(); // ошибка, так как displayNum4() - private
}
}
Так как ClassD - наследник класса ClassA, то мы можем напрямую использовать методы и
поля ClassA без создания объекта. И здесь нам опять недоступны поля и методы private, и также
нам недоступны поля и методы с модификатором доступа по умолчанию. В то же время в
отличие от находящегося в том же пакете класса ClassC в классе ClassD мы можем использовать
методы и поля с доступом protected.
Инкапсуляция
Казалось бы, почему бы не объявить все переменные и методы с модификатором public?
Однако использование различных модификаторов гарантирует, что данные не будут искажены
или изменены не надлежащим образом. Подобное сокрытие данных называется инкапсуляцией.
А вместо непосредственного использования полей, как правило, используют методы
доступа:
class Book{
private String name;
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
И затем вместо непосредственной работы с полем name в классе Book мы будем работать с
методами, которые устанавливает значение этого поля и возвращают его.
Do'stlaringiz bilan baham: |