#ооп #инкапсуляция
Начал изучать объектно-ориентированное программирование. Со всеми принципами разобрался, но не могу до конца осмыслить, для чего нужна инкапсуляция. В моем понимании это контроль входящих данных и более ничего, но разве нет ничего более существенного?
Ответы
Ответ 1
Более того - инкапсуляция: это самый важный принцип не только ООП, а программирования в принципе. Наследование, и полиморфизм - это строго говоря не принципы вовсе, скорее некоторые свойства ООП-систем связанные с переиспользованием кода. Почему же так важна инкапсуляция: представьте себе код не учебной задачки, а код огромного проекта, где только кода (со всякими библиотеками) на гигабайт. А теперь представьте, что в этом коде всё крепко-накрепко друг с другом перевязано. Как думаете, возможно будет такой код анализировать в принципе? Даже если предположить что возможно: то очевидно изменение каждого метода будет провоцировать понижение стабильности. ООП старается проецировать реальный мир на код: в реальном мире вода, налитая в чашку не будет проникать в керамику, кнопка от клавиатуры не будет участвовать в вычислениях, а человеческий мозг не будет помогать сердцу толкать кровь. А принцип инкапсуляции - это и есть принцип устранения связей, то есть то, что позволяет объектам не "перемешиваться". Именно обособление, которое даёт инкапсуляция - позволяет уложить даже огромные объёмы кода в голову, разделяй и властвуй - это ещё древняя поговорка для реального мира отлично работает и для мира цифрового. А также дополнительно защищает вас от ошибок: компьютер не перестанет работать, если случайно сломать кнопку от клавиатуры(инкапсулированный код). Простота кода объекта X как-раз измеряется количеством открытых связей между объектом X и другими объектами - то есть если этих связей очень много: то очень проблематично положить объект X к себе в голову, проблематично даже дать объективное название объекту X- так как он даёт о себе слишком много разнородной информации. Инкапсуляция проявляется не только в private и protected. Метод класса инкапсулирует в себе алгоритм и переменные. Вы можете не бояться делать неразборчивые четырёхъярусные алгоритмы внутри метода класса, так как программист которому понадобится класс будет смотреть не на содержимое метода, а на название метода. Это тоже инкапсуляция, работает принцип сокрытия - программисту неважно что внутри, при этом он понимает как всё работает. Тоже самое относится к функциям-замыканиям: они для того и созданы, чтобы обособлять внутри себя алгоритм с переменными для его работы. То есть функции тоже работают прежде всего на инкапсуляцию - т.к. переменные внутри функции, алгоритм их использующий, может совершенно не беспокоить того кто использует функцию. И я бы даже сказал, что функции в современном программировании инкапсулируют гораздо больше, чем модификаторы видимости в классах - яркие примеры сплошь и рядом на JavaScript. Подытожу свой ответ - инкапсуляция это почти что то же самое, что и обособление. Именно обособление - ключевая вещь, которая помогает систему любых размеров уложить в голове. Инкапсуляция уменьшает количество связей между объектами - думать о них, и прокручивать в голове механизм их работы становится гораздо проще, разработка ускоряется. Разделяй и властвуй. Однако это верно только для средних-больших проектов, с множеством подключаемых библиотек. На небольшой задаче реальную пользу инкапсуляции увидеть можно только когда пренебрегая использованием функций/классов, у вас образуется слишком большой стек глобальных переменных, от которых голова пойдёт кругом.Ответ 2
Инкапсуляция - сокрытие данных. Приведу простой пример. Допустим у нас есть прямоугольник, у которого поля открыты (модификатор доступа public): public class Rectangle { public int width; public int height; } Вы же можете написать следующий код: Rectangle rect = new Rectangle(); rect.width = -1; rect.height = -1; С точки зрения компилятора все отлично, -1 имеет тип int, ничего незаконного мы не делаем. Но Вы то понимаете, что так делать нельзя (что означает отрицательная высота?) и хочется как-то избавиться от этой ошибки. Что можно сделать? А можно сделать следующее: public class Rectangle { private int width; private int height; public void setHeight(int value) { if(value <= 0) throw new IllegalArgumentException(); height = value; } public int getHeight() { return height; } //Тоже самое с width } Что изменилось? У поля height модификатор доступа стал private, то есть теперь за границамы класса мы не можем получить к нему доступ. Но ведь это тоже не дело, мы, скорее всего, захотим использовать это поле у себя в коде. Для этого был добавлен метод (называется геттер) getHeight(). Также, добавился метод (называется сеттер), который, собственно, и решает нашу проблему (с отрицательными значениями). Теперь, если попытаться сделать следующее: Rectangle rect = new Rectangle(); rect.setHeight(-1) ; //IllegalArgumentException! Будет ошибка! Таким образом, мы "скрыли" поля (используя модификатор private) и задаем их значение через методы (называемые сеттерами), в которых можем проверять данные на корректность (валидация). Теперь другие программисты (если Вы работаете в команде) или Вы сами не смогут "поламать" Ваш обьект (сделать так чтобы что-то перестало работать). Разумеется, пример приведенный мною, является очень простым. На практике (когда Вы работаете в команде) все не так очевидно. В конце концов, Вы можете просто ошибиться и, допустим, поделить на 0 (это Java сообщит Вам об ошибке, а на C++ программа аварийно завершиться и потом гадай в какой строке из миллиона что-то не так!!!).Ответ 3
Инкапсуляция (encapsulation) - это механизм, который объединяет данные и код, манипулирующий этими данными, а также защищает и то, и другое от внешнего вмешательства или неправильного использования. (from codenet.ru) Инкапсуляция нужна для того, что бы пользователь не мог использовать не предназначенный для него функционал. Почитайте Гради Буча "Объектно-ориентированный анализ и проектирование с примерами приложений на С++". У него нормально расписано и примеры интересные. Система должна быть закрыта, как Ганнибал Лектор в камере. Мы знаем как узнать жив ли он еще и как дать ему покушать. Больше взаимодействовать с ним нельзя. Могут быть последствия. Очередной апдейт. Компьютерную программу можно рассматривать как систему, состоящую из функционала предназначенного для пользователя и функционала предназначеного для служебного использования. Служебный функционал следует скрывать, что бы не вводить пользователя в недоумение и не дать ему возможности изменить внутреннее состояние системы не подобающим образом.Ответ 4
Объект "знает" свое состояние, и когда его "попросите", чтобы свое состояние изменил, сделает то так, чтобы его состояние было всегда консистентным. Пример: Объект: Время в виде минуты:секунды вместе с методом увеличения на любые количество секунд. Состояние: 7:42. Просьба: Увеличивай свое состояние на 20 секунд. Новое состояние: 8:02. Когда бы вы сохраняли минуты и секунды в 2 независимых переменных, тогда на всяком месте программы, где бы вы добавили секунды, должны были опять и опять проверять, если не нужно изменить тоже количество минут - и могли бы это забыть. И каждому, кто бы хотел добавить что-то до вашей программы, указать на это.Ответ 5
Как указано в википедии с трактовкой термина не все просто. Под ним могут подразумевать механизм ограничения доступа и/или конструкцию языка позволяющую упаковывать данные и методы обработки этих данных. Если по ограничению доступа вам много написали и это достаточно просто для понимания, то с упаковкой у начинающих все плохо и с чистой совестью для каждого поля класса создаются пара get set методов. В подавляющем большинстве случаев это явный признак того, что имеет место нарушение инкапсуляции. Объект должен сам обрабатывать свои данные, а не быть просто контейнером для них. Объект это данные + поведение, в противном случае это не объект в том смысле, который вкладывал в него автор ООП. И на мой взгляд это является более важным, чем просто механизм ограничения доступа.
Комментариев нет:
Отправить комментарий