Инкапсуляция в Java
Данная статья:
- написана командой Vertex Academy.
- это одна из статей из нашего "Самоучителя по Java"
Привет! Это статья про инкапсуляцию - один из принципов ООП. Если Вы не знаете, что такое принципы ООП - почитайте эту статью:
Что такое инкапсуляция
В программировании очень важна безопасность. В ООП безопасность обеспечивается по-своему - с помощью принципа инкапсуляции (с англ. "encapsulation"). Инкапсуляцию можно перевести как "положить что-то во что-то", или для простоты "обернуть в капсулу" 🙂
С помощью инкапсуляции мы защищаем данные от неправомерного использования.
Если еще проще
Как не удивительно, мы можем видеть инкапсуляцию и в повседневной жизни. Например, Ваше имя и фамилия находится в относительно свободном доступе - они известны всем Вашим знакомым. Но Вы не хотели бы, чтобы кто-то знал номер Вашей кредитки и ее пинкод? Если проводить аналогию с методами, Вы не хотели бы, чтобы кто-то, например, ездил на Вашей машине, спал в Вашей кровати и ел Вашу кашу? 🙂 Даже свои секреты мы доверяем ограниченному числу людей - можно сказать регулируем права доступа.
Для того, чтобы никто не получил доступ к тому, что не следует, мы пользуемся разными средствами для обеспечения безопасности - ставим замки на двери, пароль на телефон или ноутбук, и т.д.
Точно так же и в Java - мы пользуемся разными средствами для обеспечения принципа инкапсуляции. Но как же мы это делаем?
Как применяется инкапсуляция
Есть несколько способов регулировать доступ к нашим данным. Основные это:
- Модификаторы доступа (Access modifiers)
- Геттеры и Сеттеры (Getters and Setters)
Модификаторы доступа
Модификаторы доступа - это специальные слова, которые показывают, кому нельзя, а кому можно пользоваться данными.
Существуют четыре модификатора доступа:
На самом деле по названиям не сложно понять, что каждый из них означает:
- public - "публичный, доступный всем"
- default - "по умолчанию". Когда мы не пишем модификатора доступа (как мы это делали в наших предыдущих уроках), он по умолчанию имеет значение default. Данные с этим модификатором видны в пределах package.
- protected - "защищенный". На самом деле это то же самое, что и default, только доступ имеют еще и классы-наследники.
- private - "частный, личный". Такие данные видны только самому классу.
Модификаторы доступа пишутся перед названиями переменных, методов и даже классов:
Как это обеспечивает безопасность? Давайте попробуем создать класс, в котором будет только одна переменная - String s. Допустим она имеет модификатор public:
1 2 3 |
class MyClass { public String s = "Hello World!"; } |
Теперь попробуем вывести значение этой переменной на экран:
1 2 3 4 5 6 7 8 |
public class Test { public static void main(String[] args) { MyClass obj = new MyClass(); System.out.println(obj.s); } } |
Отлично! Получили:
Тем не менее, точно так же мы можем и поменять эту переменную. Например:
1 2 3 4 5 6 7 8 9 10 |
public class Test { public static void main(String[] args) { MyClass obj = new MyClass(); System.out.println(obj.s); obj.s = "It's modified!"; System.out.println(obj.s); } } |
Получим:
Как видите, мы спокойно поменяли строку. А это не очень хорошо 🙁 Потому что так кто угодно из любой части программы сможет ее изменить.
Если мы не хотим этого - поменяем модификатор с public на private:
1 2 3 |
class MyClass { private String s = "Hello World!"; } |
Теперь при попытке доступа к переменной s - будь то чтение или запись - у нас возникнет ошибка:
Вот так мы защитили переменную от злодеев 🙂
Сейчас мы рассказали про модификаторы доступа в двух словах. Подробнее про модификаторы можете прочитать тут:
Геттеры и Сеттеры
Ну, вот мы защитили переменную - но ее же надо как-то менять? 🙂 Если влиять на переменную напрямую считается плохой практикой, то как по-другому, правильно можно изменять переменные?
Для этого существуют специальные методы - так называемые Геттеры и Сеттеры. Ну, они не то чтобы специальные - просто настолько часто используются, что были вынесены в отдельную категорию методов.
Геттер - от англ. "get", "получать" - это метод, с помощью которого мы получаем значение переменной, т.е. ее читаем. Например, создадим Геттер для нашей переменной s:
1 2 3 4 5 6 7 8 |
class MyClass { private String s = "Hello World!"; public String getS() { return s; } } |
Сеттер - от англ. "set", "устанавливать" - это метод, с помощью которого мы меняем, или задаем значение переменной. Допишем Сеттер для переменной s:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class MyClass { private String s = "Hello World!"; public String getString() { return s; } public void setS(String newValue) { s = newValue; } } |
Отлично! Теперь, если переписать наш main() по-правильному, получим:
1 2 3 4 5 6 7 8 9 10 |
public class Test { public static void main(String[] args) { MyClass obj = new MyClass(); System.out.println(obj.getS()); obj.setS("It's modified!"); System.out.println(obj.getS()); } } |
Как видите, вместо того чтобы напрямую стучаться к переменной, мы меняем ее с помощью сеттеров и сеттеров. Мы получаем:
Если результат такой же, зачем это все было менять?
Тут у нас в каждом методе всего по одной строчке, но если нам понадобится добавить какую-то логику - например, присваивать новое значение строке s только если она больше какой-то длины, или если содержит слово "Java". Главное, мы получаем контроль над происходящим - никто не может просто так менять или читать наши переменные.
Подробнее про Гетеры и Сеттеры можете прочитать тут:
Итого
Итак, теперь Вы знаете, что такое инкапсуляция и как она выглядит на практике. Напоследок хотелось бы сказать:
Создавая новый класс, Вы должны думать не только о функциональности, но и о безопасности - кто и при каких условиях может получать доступ к внутренностям Вашего класса.
Надеемся, что наша статья была Вам полезна. Можно записаться к нам на курсы по Java на сайте.