27. Java – Инкапсуляция
Инкапсуляция – это одна из четырёх фундаментальных концепций ООП. Названия оставшихся трёх: наследование, полиморфизм, абстракция.
Инкапсуляция в Java является механизмом обёртывания данных (переменных) и кода, работающего с данными (методами), в одно целое. В инкапсуляции переменные класса будут скрыты от других классов и доступ к ним может быть получен только с помощью метода их текущего класса. По-другому это называется скрытием данных.
Для достижения инкапсуляции в Java:
- Объявите переменные класса как private.
- Предоставьте public к методам установки и получения (сеттеру и геттеру) для изменения и просмотра значений переменных.
Пример
Ниже приведён пример процесса инкапсуляции в Java:
/* File name : EncapTest.java */ public class EncapTest < private String name; private String idNum; private int age; public int getAge() < return age; >public String getName() < return name; >public String getIdNum() < return idNum; >public void setAge(int newAge) < age = newAge; >public void setName(String newName) < name = newName; >public void setIdNum(String newId) < idNum = newId; >>
Публичные методы setXXX() и getXXX() являются точками доступа переменных экземпляра класса EncapTest. Обычно эти методы упоминаются как геттеры и сеттеры. Следовательно, любой класс, который хочет получить доступ к переменным, должен получить к ним доступ через эти геттеры и сеттеры.
Доступ к переменным класса EncapTest можно получить следующей программой:
/* File name : RunEncap.java */ public class RunEncap < public static void main(String args[]) < EncapTest encap = new EncapTest(); encap.setName("Олег"); encap.setAge(28); encap.setIdNum("12343ms"); System.out.print("Имя: " + encap.getName() + ", возраст: " + encap.getAge()); >>
Мы получим следующий результат:
Имя: Олег, возраст: 28
Преимущества инкапсуляции
- Поля класса можно сделать только для чтения или только для записи.
- Класс может иметь полный контроль над тем, что хранится в его полях.
Оглавление
- 1. Java – Самоучитель для начинающих
- 2. Java – Обзор языка
- 3. Java – Установка и настройка
- 4. Java – Синтаксис
- 5. Java – Классы и объекты
- 6. Java – Конструкторы
- 7. Java – Типы данных и литералы
- 8. Java – Типы переменных
- 9. Java – Модификаторы
- 10. Java – Операторы
- 11. Java – Циклы и операторы цикла
- 11.1. Java – Цикл while
- 11.2. Java – Цикл for
- 11.3. Java – Улучшенный цикл for
- 11.4. Java – Цикл do..while
- 11.5. Java – Оператор break
- 11.6. Java – Оператор continue
- 12. Java – Операторы принятия решений
- 12.1. Java – Оператор if
- 12.2. Java – Оператор if..else
- 12.3. Java – Вложенный оператор if
- 12.4. Java – Оператор switch..case
- 12.5. Java – Условный оператор (? 🙂
- 13. Java – Числа
- 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
- 13.2. Java – Метод compareTo()
- 13.3. Java – Метод equals()
- 13.4. Java – Метод valueOf()
- 13.5. Java – Метод toString()
- 13.6. Java – Метод parseInt()
- 13.7. Java – Метод Math.abs()
- 13.8. Java – Метод Math.ceil()
- 13.9. Java – Метод Math.floor()
- 13.10. Java – Метод Math.rint()
- 13.11. Java – Метод Math.round()
- 13.12. Java – Метод Math.min()
- 13.13. Java – Метод Math.max()
- 13.14. Java – Метод Math.exp()
- 13.15. Java – Метод Math.log()
- 13.16. Java – Метод Math.pow()
- 13.17. Java – Метод Math.sqrt()
- 13.18. Java – Метод Math.sin()
- 13.19. Java – Метод Math.cos()
- 13.20. Java – Метод Math.tan()
- 13.21. Java – Метод Math.asin()
- 13.22. Java – Метод Math.acos()
- 13.23. Java – Метод Math.atan()
- 13.24. Java – Метод Math.atan2()
- 13.25. Java – Метод Math.toDegrees()
- 13.26. Java – Метод Math.toRadians()
- 13.27. Java – Метод Math.random()
- 14. Java – Символы
- 14.1. Java – Метод Character.isLetter()
- 14.2. Java – Метод Character.isDigit()
- 14.3. Java – Метод Character.isWhitespace()
- 14.4. Java – Метод Character.isUpperCase()
- 14.5. Java – Метод Character.isLowerCase()
- 14.6. Java – Метод Character.toUpperCase()
- 14.7. Java – Метод Character.toLowerCase()
- 14.8. Java – Метод Character.toString()
- 15. Java – Строки
- 15.1. Java – Метод charAt()
- 15.2. Java – Метод compareTo()
- 15.3. Java – Метод compareToIgnoreCase()
- 15.4. Java – Метод concat()
- 15.5. Java – Метод contentEquals()
- 15.6. Java – Метод copyValueOf()
- 15.7. Java – Метод endsWith()
- 15.8. Java – Метод equals()
- 15.9. Java – Метод equalsIgnoreCase()
- 15.10. Java – Метод getBytes()
- 15.11. Java – Метод getChars()
- 15.12. Java – Метод hashCode()
- 15.13. Java – Метод indexOf()
- 15.14. Java – Метод intern()
- 15.15. Java – Метод lastIndexOf()
- 15.16. Java – Метод length()
- 15.17. Java – Метод matches()
- 15.18. Java – Метод regionMatches()
- 15.19. Java – Метод replace()
- 15.20. Java – Метод replaceAll()
- 15.21. Java – Метод replaceFirst()
- 15.22. Java – Метод split()
- 15.23. Java – Метод startsWith()
- 15.24. Java – Метод subSequence()
- 15.25. Java – Метод substring()
- 15.26. Java – Метод toCharArray()
- 15.27. Java – Метод toLowerCase()
- 15.28. Java – Метод toString()
- 15.29. Java – Метод toUpperCase()
- 15.30. Java – Метод trim()
- 15.31. Java – Метод valueOf()
- 15.32. Java – Классы StringBuilder и StringBuffer
- 15.32.1. Java – Метод append()
- 15.32.2. Java – Метод reverse()
- 15.32.3. Java – Метод delete()
- 15.32.4. Java – Метод insert()
- 15.32.5. Java – Метод replace()
- 16. Java – Массивы
- 17. Java – Дата и время
- 18. Java – Регулярные выражения
- 19. Java – Методы
- 20. Java – Потоки ввода/вывода, файлы и каталоги
- 20.1. Java – Класс ByteArrayInputStream
- 20.2. Java – Класс DataInputStream
- 20.3. Java – Класс ByteArrayOutputStream
- 20.4. Java – Класс DataOutputStream
- 20.5. Java – Класс File
- 20.6. Java – Класс FileReader
- 20.7. Java – Класс FileWriter
- 21. Java – Исключения
- 21.1. Java – Встроенные исключения
- 22. Java – Вложенные и внутренние классы
- 23. Java – Наследование
- 24. Java – Переопределение
- 25. Java – Полиморфизм
- 26. Java – Абстракция
- 27. Java – Инкапсуляция
- 28. Java – Интерфейсы
- 29. Java – Пакеты
- 30. Java – Структуры данных
- 30.1. Java – Интерфейс Enumeration
- 30.2. Java – Класс BitSet
- 30.3. Java – Класс Vector
- 30.4. Java – Класс Stack
- 30.5. Java – Класс Dictionary
- 30.6. Java – Класс Hashtable
- 30.7. Java – Класс Properties
- 31. Java – Коллекции
- 31.1. Java – Интерфейс Collection
- 31.2. Java – Интерфейс List
- 31.3. Java – Интерфейс Set
- 31.4. Java – Интерфейс SortedSet
- 31.5. Java – Интерфейс Map
- 31.6. Java – Интерфейс Map.Entry
- 31.7. Java – Интерфейс SortedMap
- 31.8. Java – Класс LinkedList
- 31.9. Java – Класс ArrayList
- 31.10. Java – Класс HashSet
- 31.11. Java – Класс LinkedHashSet
- 31.12. Java – Класс TreeSet
- 31.13. Java – Класс HashMap
- 31.14. Java – Класс TreeMap
- 31.15. Java – Класс WeakHashMap
- 31.16. Java – Класс LinkedHashMap
- 31.17. Java – Класс IdentityHashMap
- 31.18. Java – Алгоритмы Collection
- 31.19. Java – Iterator и ListIterator
- 31.20. Java – Comparator
- 32. Java – Дженерики
- 33. Java – Сериализация
- 34. Java – Сеть
- 34.1. Java – Обработка URL
- 35. Java – Отправка Email
- 36. Java – Многопоточность
- 36.1. Java – Синхронизация потоков
- 36.2. Java – Межпоточная связь
- 36.3. Java – Взаимная блокировка потоков
- 36.4. Java – Управление потоками
- 37. Java – Основы работы с апплетами
- 38. Java – Javadoc
Руководство по Java Core. Инкапсуляция.
Инкапсуляция – это механизм “обёртывания” данных или кода, который работает с этими данными в отдельный модуль. Инкапсулированные, таким образом, переменные, отделены от других классов и доступ к ним возможен только с помощью методов класса, который содержит эти переменные.
Таким образом, мы, как бы, “прячем” переменные от остальных классов, что облегчает работу с ними в дальнейшем.
В ящике программирования Java, инкапсуляция достигается путём:
- Объявления переменной класса приватной (модификатор доступа private)
- Создание публичных (модификатор доступа public) методов для получения и изменения значения переменной.
Для понимания того, как это работает на практике рассмотрим пример простого приложения.
public class Company < private String companyName; private String companySphere; private String projectName; public String getCompanyName() < return companyName; >public void setCompanyName(String companyName) < this.companyName = companyName; >public String getCompanySphere() < return companySphere; >public void setCompanySphere(String companySphere) < this.companySphere = companySphere; >public String getProjectName() < return projectName; >public void setProjectName(String projectName) < this.projectName = projectName; >@Override public String toString() < return "=============================\n" + "Company Name: " + companyName + "\nSphere:" + companySphere + "\nProject Name: " + projectName + "\n============================\n"; >>
public class CompanyRunner < public static void main(String[] args) < Company uksatse = new Company(); uksatse.setCompanyName("UkSATSE"); uksatse.setCompanySphere("Aviation"); uksatse.setProjectName("SkybleLib"); System.out.println("UkSATSE info:"); System.out.println(uksatse); >>
В результате работы программы мы получим следующий результат:
/*Some system messages*/ UkSATSE info: ============================= Company Name: UkSATSE Sphere:Aviation Project Name: SkybleLib ============================
Как мы видим, доступ к переменным класса Company из класса CompanyRunner возможен только с помощью методов getXXX и setXXX.
Инкапсуляция даёт нам следующие преимущества:
- Класс имеет полный контроль над всеми своими переменными.
- Другим классам, которые будут использовать данный класс не интересно, как именно хранятся данные в классе. В случае, если нам будет необходимо изменить тип данных, то нам не придётся вносить изменения в другие классы.
- Мы можем делать поля только для чтения или только для записи.
В этом уроке мы более глубоко изучили что такое инкапсуляция и как она применяется в языке программирования Java.
В следующем уроке мы изучим такое понятие в ООП как абстракция.
Инкапсуляция в Java
Привет! Это статья про инкапсуляцию — один из принципов ООП. Если Вы не знаете, что такое принципы ООП — почитайте эту статью:
Что такое инкапсуляция
В программировании очень важна безопасность. В ООП безопасность обеспечивается по-своему — с помощью принципа инкапсуляции (с англ. «encapsulation»). Инкапсуляцию можно перевести как «положить что-то во что-то», или для простоты «обернуть в капсулу»
С помощью инкапсуляции мы защищаем данные от неправомерного использования.
Если еще проще
Как не удивительно, мы можем видеть инкапсуляцию и в повседневной жизни. Например, Ваше имя и фамилия находится в относительно свободном доступе — они известны всем Вашим знакомым. Но Вы не хотели бы, чтобы кто-то знал номер Вашей кредитки и ее пинкод? Если проводить аналогию с методами, Вы не хотели бы, чтобы кто-то, например, ездил на Вашей машине, спал в Вашей кровати и ел Вашу кашу? Даже свои секреты мы доверяем ограниченному числу людей — можно сказать регулируем права доступа.
Для того, чтобы никто не получил доступ к тому, что не следует, мы пользуемся разными средствами для обеспечения безопасности — ставим замки на двери, пароль на телефон или ноутбук, и т.д.
Точно так же и в Java — мы пользуемся разными средствами для обеспечения принципа инкапсуляции. Но как же мы это делаем?
Как применяется инкапсуляция
Есть несколько способов регулировать доступ к нашим данным. Основные это:
- Модификаторы доступа (Access modifiers)
- Геттеры и Сеттеры (Getters and Setters)
Модификаторы доступа
Модификаторы доступа — это специальные слова, которые показывают, кому нельзя, а кому можно пользоваться данными.
Существуют четыре модификатора доступа:
На самом деле по названиям не сложно понять, что каждый из них означает:
- public — «публичный, доступный всем»
- default — «по умолчанию». Когда мы не пишем модификатора доступа (как мы это делали в наших предыдущих уроках), он по умолчанию имеет значение default. Данные с этим модификатором видны в пределах package.
- protected — «защищенный». На самом деле это то же самое, что и default, только доступ имеют еще и классы-наследники.
- private — «частный, личный». Такие данные видны только самому классу.
Модификаторы доступа пишутся перед названиями переменных, методов и даже классов:
Как это обеспечивает безопасность? Давайте попробуем создать класс, в котором будет только одна переменная — String s. Допустим она имеет модификатор public:
Инкапсуляция
— Привет, Амиго! Хочу посвятить сегодняшнюю лекцию инкапсуляции . Ты уже знаешь в общих чертах, что это такое.
В чем же преимущества инкапсуляции? Их достаточно много, но я могу выделить четыре, на мой взгляд, основных:
1) Валидное внутреннее состояние.
В программах часто возникают ситуации, когда несколько классов, взаимодействуют с одним и тем же объектом. В результате их совместной работы нарушается целостность данных внутри объекта — объект уже не может продолжить нормально работать.
Поэтому объект должен следить за изменениями своих внутренних данных, а еще лучше – проводить их сам.
Если мы не хотим, чтобы какая-то переменная класса менялась другими классами, мы объявляем ее private, и тогда только методы её же класса смогут получить к ней доступ. Если мы хотим, чтобы значения переменных можно было только читать, но не изменять, тогда нужно добавить public getter для нужных переменных.
Например, мы хотим, чтобы все могли узнать количество элементов в нашей коллекции, но никто не мог его поменять без нашего разрешения. Тогда мы объявляем переменную private int count и метод public getCount().
Правильное использование инкапсуляции гарантирует, что ни один класс не может получить прямой доступ к внутренним данным нашего класса и, следовательно, изменить их без контроля с нашей стороны. Только через вызов методов того же класса, что и изменяемые переменные.
Лучше исходить из того, что другие программисты всегда будут использовать твои классы самым удобным для них образом, а не самым безопасным для тебя (для твоего класса). Отсюда и ошибки, и попытки заранее избавиться от них.
2) Контроль передаваемых аргументов.
Иногда нужно контролировать аргументы, передаваемые в методы нашего класса. Например, наш класс описывает объект «человек» и позволяет задать дату его рождения. Мы должны проверять все передаваемые данные на их соответствие логике программы и логике нашего класса. Например, не допускать 13-й месяц, дату рождения 30 февраля и так далее.
— А зачем кому-то указывать в дате рождения 30 февраля?
— Во-первых – это может быть ошибка ввода данных от пользователя.
Во-вторых, прежде чем программа будет работать как часы, в ней будет много ошибок. Например, возможна такая ситуация.
Программист пишет программу для определения людей, у которых день рождения послезавтра. Например, сегодня 3 марта. Программа добавляет к текущему дню месяца число 2 и ищет всех, кто родился 5 марта. Вроде бы все верно.
Вот только, когда наступит 30 марта программа не найдет никого, т.к. в календаре нет 32 марта. В программе становится гораздо меньше ошибок, когда в методы добавляют проверку переданных данных.
— Помню, когда мы изучали ArrayList, я смотрел его код, и там была проверка индекса в методах get и set: index больше или равен нулю и меньше длины массива. Там еще кидалось исключение, если в массиве нет элемента с таким индексом.
— Да, это классический пример проверки входных данных.
3) Минимизация ошибок при изменении кода классов.
Представим, что мы написали один очень полезный класс, когда участвовали в большом проекте. Он так всем понравился, что другие программисты начали использовать его в сотнях мест в своем коде.
Класс оказался настолько полезен, что ты решил его улучшить. Но если ты удалишь какие-то методы этого класса, то код десятков людей перестанет компилироваться. Им придется срочно все переделывать. И чем больше переделок, тем больше ошибок. Ты поломаешь кучу сборок, и тебя будут ненавидеть.
А когда мы меняем методы, объявленные как private, мы знаем, что нигде нет ни одного класса, который вызывал бы эти методы. Мы можем их переделать, поменять количество параметров и их типы, и зависимый код будет работать дальше. Ну, или как минимум, компилироваться.
4) Задаем способ взаимодействия нашего объекта со сторонними объектами.
Мы можем ограничить некоторые действия, допустимые с нашим объектом. Например, мы хотим, чтобы объект можно было создать только в одном экземпляре. Даже если его создание происходит в нескольких местах проекта одновременно. И мы можем сделать это благодаря инкапсуляции.
Инкапсуляция позволяет добавлять дополнительные ограничения , которые можно превратить в дополнительные преимущества . Например, класс String реализован как immutable (неизменяемый) объект. Объект класса String неизменяем с момента создания и до момента смерти. Все методы класса String (remove, substring, …), возвращают новую строку, абсолютно не изменяя объект, у которого они были вызваны.
— Ничего себе. Вот оно как, оказывается.
— Инкапсуляция очень интересная штука.